classification
Title: cgitb.html fails if getattr call raises exception
Type: behavior Stage: test needed
Components: Library (Lib) Versions: Python 3.2, Python 3.3, Python 3.4, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: amc1, arthur.petitpierre, ggenellina
Priority: normal Keywords: easy, patch

Created on 2008-12-12 14:48 by amc1, last changed 2012-12-06 21:22 by arthur.petitpierre.

Files
File name Uploaded Description Edit
attrtest.py amc1, 2008-12-12 14:48
issue4643.patch arthur.petitpierre, 2012-12-06 21:22 patch and test case for issue 4643 review
Messages (5)
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
B:
Something went wrong - attempting to generate HTML stack trace.
Error generating HTML stack trace!
Traceback (most recent call last):
  File "attrtest.py", line 21, in <module>
    html_text = cgitb.html(sys.exc_info())
  File "C:\python26\lib\cgitb.py", line 133, in html
    vars = scanvars(reader, frame, locals)
  File "C:\python26\lib\cgitb.py", line 84, in scanvars
    value = getattr(parent, token, __UNDEF__)
  File "attrtest.py", 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:

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

SOLUTION:
if parent is not __UNDEF__:
    try:
        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
accurate.

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
solution.
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.
History
Date User Action Args
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