[Patches] [ python-Patches-763201 ] 3 bugs fixed: handling of SyntaxErrors in symbol table build
SourceForge.net
noreply@sourceforge.net
Mon, 30 Jun 2003 08:57:11 -0700
Patches item #763201, was opened at 2003-06-30 13:48
Message generated for change (Settings changed) made by jhylton
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=763201&group_id=5470
Category: Parser/Compiler
Group: Python 2.3
Status: Open
Resolution: None
>Priority: 7
Submitted By: Steven Taschuk (staschuk)
>Assigned to: Jeremy Hylton (jhylton)
Summary: 3 bugs fixed: handling of SyntaxErrors in symbol table build
Initial Comment:
All three bugs found in both 2.2.3 and 2.3b2. It's one
patch
instead of three because the fixes share a refactoring of
Python/compile.c:symtable_build.
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
st_filename.)
Bug 2: Memory leak
while True:
try:
compile('def foo(a): global a', 'spam', 'exec')
except SyntaxError:
pass
(Cause: symtable_build doesn't free c->c_symtable on
error.)
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
compile()
causes a SystemError. (Cause: see below.)
What to do about bugs 1 and 2 is obvious, but bug 3
(which was
actually reported on c.l.py) is not so clear to me. Here's
how
the problem occurs:
symtable_global() sees the global statement in foo(),
raises a
SyntaxError, increments st_errors, and returns.
Processing
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
PyEval_GetGlobals.)
But st_errors is still > 0, as it should be, so
symtable_build()
returns -1 (resp. PyNode_CompileSymtable, NULL), its
callers
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;
fail
instead and let that exception propagate. Also, as a
defensive
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
checking
st_errors immediately afterwards.)
2. Put the check for a pending exception in
PyErr_WarnExplicit()
instead of in the helper function in compile.c. (Doesn't
seem
like a common enough coding error to merit a check
there. In
symtable_node etc we deliberately let SyntaxErrors, er,
"pend"
while we do a bit more compiling, so *there* it's worth
checking.
Note that jcompile() already has a check for something
similar,
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
exception
or the squirrelled one propagate? Ick.)
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=763201&group_id=5470