Title: cgitb.html fails if getattr call raises exception
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.10, Python 3.9, Python 3.8
Status: closed Resolution: duplicate
Dependencies: Superseder: cgitb failures
View: 1047397
Assigned To: Nosy List: amc1, arthur.petitpierre, ggenellina, iritkatriel, karlcow
Priority: normal Keywords: easy, patch

Created on 2008-12-12 14:48 by amc1, last changed 2021-01-02 19:28 by iritkatriel. This issue is now closed.

File name Uploaded Description Edit amc1, 2008-12-12 14:48
issue4643.patch arthur.petitpierre, 2012-12-06 21:22 patch and test case for issue 4643 review
Pull Requests
URL Status Linked Edit
PR 24038 closed karlcow, 2021-01-01 14:14
Messages (11)
msg77672 - (view) Author: Allan Crooks (amc1) Date: 2008-12-12 14:48
If cgitb.html tries to get the value of an attribute from an object, and
the getattr call causes an exception to be raised (other than an
AttributeError), then cgitb.html fails to work:

If you run the attached file in Python 2.5.2 or 2.6, you get the
following output:


A: the letter a
Something went wrong - attempting to generate HTML stack trace.
Error generating HTML stack trace!
Traceback (most recent call last):
  File "", line 21, in <module>
    html_text = cgitb.html(sys.exc_info())
  File "C:\python26\lib\", line 133, in html
    vars = scanvars(reader, frame, locals)
  File "C:\python26\lib\", line 84, in scanvars
    value = getattr(parent, token, __UNDEF__)
  File "", line 8, in __getattr__
    return str(slf) # Intentional NameError
NameError: global name 'slf' is not defined


The problem is in the scanvars function - it offers no protection
against any unexpected exceptions that occur (that escape the getattr
call) - which can be a problem if it is the same problematic code that
caused cgitb.html to be called in the first place.

I think scanvars should catch any exceptions that come from the getattr
call and either mention that the attribute value could not be
determined, or simply omit the mention of the attribute at all.

If the line in the attached file is commented out, then the next line is
caught appropriately and formatted correctly (the offending code occurs
in the same block, but doesn't cause the same problem because it raises
an AttributeError).
msg78005 - (view) Author: Allan Crooks (amc1) Date: 2008-12-18 01:43
In terms of patching scanvars, I came up with the following solution:

if parent is not __UNDEF__:
    value = getattr(parent, token, __UNDEF__)
    vars.append((prefix + token, prefix, value))

if parent is not __UNDEF__:
        value = getattr(parent, token, __UNDEF__)
    except Exception:
        value = __UNDEF__
    vars.append((prefix + token, prefix, value))

I think this makes the most sense - it requires a small change, and it
won't have any strange side effect. One slightly undesirable aspect is
that for an attribute value which could not be determined (due to this
problem), it will say that it was "undefined", which isn't entirely

My initial patch changed value to be a string to be "could not determine
value", but if the line of code looked like this:
    print 'B:', weird.b.upper()

Then for something which shouldn't work, it would determine that the
value of weird.b.upper is the string method - which isn't what we're after.

So I would recommend my original patch (as described above) as the best
msg78457 - (view) Author: Allan Crooks (amc1) Date: 2008-12-29 15:43
In the interests of getting this fixed (and not letting it die), should
I submit a proper patch? I suppose I would have to do one for each
version of Python that is affected (which is all of them, really).
msg78503 - (view) Author: Gabriel Genellina (ggenellina) Date: 2008-12-30 04:21
I believe a patch against the trunk would be enough, but should include 
a test case.
msg177060 - (view) Author: Arthur Petitpierre (arthur.petitpierre) Date: 2012-12-06 21:22
I attached a patch containing both the fix suggested by Allan and a test case.
Tested against trunk and python2.7.
msg381025 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2020-11-15 18:52
The issue still occurs in 3.10. Python 3 version of the script:

import cgitb

class WeirdObject(object):
    def __getattr__(self, attr):
        if attr == 'a':
            return 'the letter a'
        elif attr == 'b':
            return str(slf) # Intentional NameError
        raise AttributeError(attr)

    weird = WeirdObject()
    print('A:', weird.a)
    print('B:', weird.b)
    print('C:', weird.c)
except Exception as e:
    import sys
    print('\nSomething went wrong - attempting to generate HTML stack trace.')
        html_text = cgitb.html(sys.exc_info())
        print('Error generating HTML stack trace!')
        print('Here is stack trace in HTML:\n', html_text)
msg381026 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2020-11-15 18:53
Arthur, are you interested in converting your patch to a github pull request?
msg384170 - (view) Author: karl (karlcow) * Date: 2021-01-01 14:20
Converted into GitHub PR
msg384183 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-01-01 15:17
On closer scrutiny I'm not sure this patch should be merged. 

The getattr call here has a default value, so it should not raise AttributeError. It should also not raise any other exception because a valid implementation of __getattr__ should raise only AttributeError:
msg384221 - (view) Author: karl (karlcow) * Date: 2021-01-02 13:21
> The getattr call here has a default value, so it should not raise AttributeError. It should also not raise any other exception because a valid implementation of __getattr__ should raise only AttributeError:

but probably the intent of the patch here is to surface a meaningful error with regards to the script, more than an error on the cgitb python lib itself as this is a traceback tool. A bit like an HTML validator which continue to process things to give some kind of meaning.

Diving into previous issues about scanvars

Similar The last comment is basically this issue here. 

There is a patch which is lot better for this bug and which addresses the issues here.

It has not been merged yet. Not sure why or if there is anything missing. 

Probably this bug could be closed as a duplicate of

And someone needs to push to push the latest bits for

What do you think @iritkatriel ?

I will close my PR.
msg384237 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-01-02 19:28
I agree that this can be closed as duplicate. Thanks, Karl, for the research.
Date User Action Args
2021-01-02 19:28:42iritkatrielsetstatus: open -> closed
superseder: cgitb failures
messages: + msg384237

resolution: duplicate
stage: patch review -> resolved
2021-01-02 13:21:57karlcowsetmessages: + msg384221
2021-01-01 15:17:00iritkatrielsetmessages: + msg384183
2021-01-01 15:16:50iritkatrielsetmessages: - msg384182
2021-01-01 15:16:10iritkatrielsetmessages: + msg384182
2021-01-01 14:20:03karlcowsetmessages: + msg384170
2021-01-01 14:14:09karlcowsetnosy: + karlcow

pull_requests: + pull_request22878
stage: test needed -> patch review
2020-11-15 18:53:23iritkatrielsetmessages: + msg381026
2020-11-15 18:52:40iritkatrielsetnosy: + iritkatriel

messages: + msg381025
versions: + Python 3.8, Python 3.9, Python 3.10, - Python 2.7, Python 3.2, Python 3.3, Python 3.4
2012-12-06 21:22:31arthur.petitpierresetfiles: + issue4643.patch

nosy: + arthur.petitpierre
messages: + msg177060

keywords: + patch
2012-10-02 05:55:20ezio.melottisetkeywords: + easy
stage: test needed
versions: + Python 2.7, Python 3.2, Python 3.3, Python 3.4, - Python 2.6, Python 3.0
2008-12-30 04:21:45ggenellinasetmessages: + msg78503
2008-12-29 15:43:06amc1setmessages: + msg78457
2008-12-20 14:35:51loewissetversions: - Python 2.5.3
2008-12-18 01:43:44amc1setmessages: + msg78005
2008-12-16 00:28:58ggenellinasetnosy: + ggenellina
2008-12-12 14:54:11amc1settype: behavior
2008-12-12 14:48:32amc1create