Issue763201
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.
Created on 2003-06-30 13:48 by staschuk, last changed 2022-04-10 16:09 by admin. This issue is now closed.
Files | ||||
---|---|---|---|---|
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 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.) |
|||
msg44171 - (view) | Author: Steven Taschuk (staschuk) | Date: 2003-07-01 17:31 | |
Logged In: YES user_id=666873 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. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-10 16:09:33 | admin | set | github: 38750 |
2003-06-30 13:48:26 | staschuk | create |