This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: 3 bugs fixed: handling of SyntaxErrors in symbol table build
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: jhylton Nosy List: jhylton, staschuk
Priority: high Keywords: patch

Created on 2003-06-30 13:48 by staschuk, last changed 2022-04-10 16:09 by admin. This issue is now closed.

File name Uploaded Description Edit
symtable-errors.patch staschuk, 2003-06-30 13:48
Messages (2)
msg44170 - (view) Author: Steven Taschuk (staschuk) Date: 2003-06-30 13:48
All three bugs found in both 2.2.3 and 2.3b2.  It's one 
instead of three because the fixes share a refactoring of

Bug 1:  Wrong file name

    import symtable
    symtable.symtable('def foo(a): global a', 'spam', 'exec')

The error message says '<string>' instead of 'spam'.
(Cause: PyNode_CompileSymtable doesn't set 

Bug 2:  Memory leak

    while True:
            compile('def foo(a): global a', 'spam', 'exec')
        except SyntaxError:

(Cause: symtable_build doesn't free c->c_symtable on 

The patch is missing a test case for this one; I don't see 
how to write it.

Bug 3:  Exception clobbered

    def foo(a):
        global a  # SyntaxError

    def bar():
        b = 1
        global b  # SyntaxWarning

Running this as a script, the SyntaxWarning is issued, 
and then
the interpreter dies silently (that is, without printing a
traceback reporting the SyntaxError).  Compiling it with 
causes a SystemError.  (Cause: see below.)

What to do about bugs 1 and 2 is obvious, but bug 3 
(which was
actually reported on is not so clear to me.  Here's 
the problem occurs:

symtable_global() sees the global statement in foo(), 
raises a
SyntaxError, increments st_errors, and returns.  
continues.  Later, symtable_global() sees the global 
statement in
bar() and issues a warning by (indirectly) calling
PyErr_WarnExplicit().  This call clears the SyntaxError, 
which is
still pending at that time.  (It's actually cleared during the
attempt to import the warnings module, in 
PyImport_Import, which
seems to think the exception was raised in 
But st_errors is still > 0, as it should be, so 
returns -1 (resp.  PyNode_CompileSymtable, NULL), its 
return their error values, etc., until eventually PyErr_Print
tries to print the exception that isn't there.

What the patch implements is this:

Do not issue SyntaxWarnings if an exception is pending; 
instead and let that exception propagate.  Also, as a 
measure against other bugs of this type (present and 
future), when
returning with error from symtable_build(), verify that 
there's an
exception pending (and raise SystemError if not).  Finally,
refactor symtable_build() so PyNode_CompileSymtable 
can use it and
thereby benefit from that defensive measure.

Alternatives (and why I don't like them):

1. Do not try to continue processing after a SyntaxError is
raised.  (Seems like the Right Thing to me, but also 
seems to be
contrary to the intent of the existing code.  There are 
oodles of
places in compile.c which call symtable_node without 
st_errors immediately afterwards.)

2. Put the check for a pending exception in 
instead of in the helper function in compile.c.  (Doesn't 
like a common enough coding error to merit a check 
there.  In
symtable_node etc we deliberately let SyntaxErrors, er, 
while we do a bit more compiling, so *there* it's worth 
Note that jcompile() already has a check for something 
though not for the symbol-table-building phase.)

3. Squirrel the pending exception away, issue the 
warning, then
restore the exception.  (Not worth the bother, IMO.  And 
if the
warning gets strengthened into an exception, should that 
or the squirrelled one propagate?  Ick.)
msg44171 - (view) Author: Steven Taschuk (staschuk) Date: 2003-07-01 17:31
Logged In: YES 

Just noticed another alternative: leave the checking of 
whether a global statement declares a function parameter 
global to the later pass.  There's already a check for this 
condition in symtable_load_symbols (with a different error 
message, which is a subject for another patch).

The problem with this idea is that it breaks 
symtable.symtable(), which only uses symtable_build.  Thus this 
function would no longer raise SyntaxErrors for this case.
Date User Action Args
2022-04-10 16:09:33adminsetgithub: 38750
2003-06-30 13:48:26staschukcreate