Check the result of PySet_Contains() for error in Python/symtable.c (GH-109146)

This commit is contained in:
Serhiy Storchaka 2023-09-08 19:57:41 +03:00 committed by GitHub
parent 501f2dc527
commit 87a7faf6b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 57 additions and 15 deletions

View File

@ -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) {