mirror of https://github.com/python/cpython
Check the result of PySet_Contains() for error in Python/symtable.c (GH-109146)
This commit is contained in:
parent
501f2dc527
commit
87a7faf6b6
|
@ -523,6 +523,7 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
||||||
PyObject *bound, PyObject *local, PyObject *free,
|
PyObject *bound, PyObject *local, PyObject *free,
|
||||||
PyObject *global, PyObject *type_params, PySTEntryObject *class_entry)
|
PyObject *global, PyObject *type_params, PySTEntryObject *class_entry)
|
||||||
{
|
{
|
||||||
|
int contains;
|
||||||
if (flags & DEF_GLOBAL) {
|
if (flags & DEF_GLOBAL) {
|
||||||
if (flags & DEF_NONLOCAL) {
|
if (flags & DEF_NONLOCAL) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
|
@ -543,14 +544,22 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
||||||
"nonlocal declaration not allowed at module level");
|
"nonlocal declaration not allowed at module level");
|
||||||
return error_at_directive(ste, name);
|
return error_at_directive(ste, name);
|
||||||
}
|
}
|
||||||
if (!PySet_Contains(bound, name)) {
|
contains = PySet_Contains(bound, name);
|
||||||
|
if (contains < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!contains) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"no binding for nonlocal '%U' found",
|
"no binding for nonlocal '%U' found",
|
||||||
name);
|
name);
|
||||||
|
|
||||||
return error_at_directive(ste, name);
|
return error_at_directive(ste, name);
|
||||||
}
|
}
|
||||||
if (PySet_Contains(type_params, name)) {
|
contains = PySet_Contains(type_params, name);
|
||||||
|
if (contains < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (contains) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"nonlocal binding not allowed for type parameter '%U'",
|
"nonlocal binding not allowed for type parameter '%U'",
|
||||||
name);
|
name);
|
||||||
|
@ -599,17 +608,29 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
||||||
Note that having a non-NULL bound implies that the block
|
Note that having a non-NULL bound implies that the block
|
||||||
is nested.
|
is nested.
|
||||||
*/
|
*/
|
||||||
if (bound && PySet_Contains(bound, name)) {
|
if (bound) {
|
||||||
SET_SCOPE(scopes, name, FREE);
|
contains = PySet_Contains(bound, name);
|
||||||
ste->ste_free = 1;
|
if (contains < 0) {
|
||||||
return PySet_Add(free, name) >= 0;
|
return 0;
|
||||||
|
}
|
||||||
|
if (contains) {
|
||||||
|
SET_SCOPE(scopes, name, FREE);
|
||||||
|
ste->ste_free = 1;
|
||||||
|
return PySet_Add(free, name) >= 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* If a parent has a global statement, then call it global
|
/* If a parent has a global statement, then call it global
|
||||||
explicit? It could also be global implicit.
|
explicit? It could also be global implicit.
|
||||||
*/
|
*/
|
||||||
if (global && PySet_Contains(global, name)) {
|
if (global) {
|
||||||
SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
|
contains = PySet_Contains(global, name);
|
||||||
return 1;
|
if (contains < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (contains) {
|
||||||
|
SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ste->ste_nested)
|
if (ste->ste_nested)
|
||||||
ste->ste_free = 1;
|
ste->ste_free = 1;
|
||||||
|
@ -712,8 +733,19 @@ analyze_cells(PyObject *scopes, PyObject *free, PyObject *inlined_cells)
|
||||||
scope = PyLong_AS_LONG(v);
|
scope = PyLong_AS_LONG(v);
|
||||||
if (scope != LOCAL)
|
if (scope != LOCAL)
|
||||||
continue;
|
continue;
|
||||||
if (!PySet_Contains(free, name) && !PySet_Contains(inlined_cells, name))
|
int contains = PySet_Contains(free, name);
|
||||||
continue;
|
if (contains < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!contains) {
|
||||||
|
contains = PySet_Contains(inlined_cells, name);
|
||||||
|
if (contains < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!contains) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Replace LOCAL with CELL for this name, and remove
|
/* Replace LOCAL with CELL for this name, and remove
|
||||||
from free. It is safe to replace the value of name
|
from free. It is safe to replace the value of name
|
||||||
in the dict, because it will not cause a resize.
|
in the dict, because it will not cause a resize.
|
||||||
|
@ -764,7 +796,11 @@ update_symbols(PyObject *symbols, PyObject *scopes,
|
||||||
long scope, flags;
|
long scope, flags;
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
flags = PyLong_AS_LONG(v);
|
flags = PyLong_AS_LONG(v);
|
||||||
if (PySet_Contains(inlined_cells, name)) {
|
int contains = PySet_Contains(inlined_cells, name);
|
||||||
|
if (contains < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (contains) {
|
||||||
flags |= DEF_COMP_CELL;
|
flags |= DEF_COMP_CELL;
|
||||||
}
|
}
|
||||||
v_scope = PyDict_GetItemWithError(scopes, name);
|
v_scope = PyDict_GetItemWithError(scopes, name);
|
||||||
|
@ -822,9 +858,15 @@ update_symbols(PyObject *symbols, PyObject *scopes,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/* Handle global symbol */
|
/* Handle global symbol */
|
||||||
if (bound && !PySet_Contains(bound, name)) {
|
if (bound) {
|
||||||
Py_DECREF(name);
|
int contains = PySet_Contains(bound, name);
|
||||||
continue; /* it's a global */
|
if (contains < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!contains) {
|
||||||
|
Py_DECREF(name);
|
||||||
|
continue; /* it's a global */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Propagate new free symbol up the lexical stack */
|
/* Propagate new free symbol up the lexical stack */
|
||||||
if (PyDict_SetItem(symbols, name, v_free) < 0) {
|
if (PyDict_SetItem(symbols, name, v_free) < 0) {
|
||||||
|
|
Loading…
Reference in New Issue