diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2023-09-08 16:57:41 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-08 16:57:41 (GMT) |
commit | 87a7faf6b68c8076e640a9a1347a255f132d8382 (patch) | |
tree | 96090c2d68cd9c737da439d77e6743e68b95bab2 | |
parent | 501f2dc527010a4fe17026b3f352d72b01228b6f (diff) | |
download | cpython-87a7faf6b68c8076e640a9a1347a255f132d8382.zip cpython-87a7faf6b68c8076e640a9a1347a255f132d8382.tar.gz cpython-87a7faf6b68c8076e640a9a1347a255f132d8382.tar.bz2 |
Check the result of PySet_Contains() for error in Python/symtable.c (GH-109146)
-rw-r--r-- | Python/symtable.c | 72 |
1 files changed, 57 insertions, 15 deletions
diff --git a/Python/symtable.c b/Python/symtable.c index 217e6f5..7eef6f7 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -523,6 +523,7 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, PyObject *bound, PyObject *local, PyObject *free, PyObject *global, PyObject *type_params, PySTEntryObject *class_entry) { + int contains; if (flags & DEF_GLOBAL) { if (flags & DEF_NONLOCAL) { 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"); 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, "no binding for nonlocal '%U' found", 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, "nonlocal binding not allowed for type parameter '%U'", 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 is nested. */ - if (bound && PySet_Contains(bound, name)) { - SET_SCOPE(scopes, name, FREE); - ste->ste_free = 1; - return PySet_Add(free, name) >= 0; + if (bound) { + contains = PySet_Contains(bound, name); + if (contains < 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 explicit? It could also be global implicit. */ - if (global && PySet_Contains(global, name)) { - SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); - return 1; + if (global) { + contains = PySet_Contains(global, name); + if (contains < 0) { + return 0; + } + if (contains) { + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); + return 1; + } } if (ste->ste_nested) ste->ste_free = 1; @@ -712,8 +733,19 @@ analyze_cells(PyObject *scopes, PyObject *free, PyObject *inlined_cells) scope = PyLong_AS_LONG(v); if (scope != LOCAL) continue; - if (!PySet_Contains(free, name) && !PySet_Contains(inlined_cells, name)) - continue; + int contains = PySet_Contains(free, name); + 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 from free. It is safe to replace the value of name in the dict, because it will not cause a resize. @@ -764,7 +796,11 @@ update_symbols(PyObject *symbols, PyObject *scopes, long scope, flags; assert(PyLong_Check(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; } v_scope = PyDict_GetItemWithError(scopes, name); @@ -822,9 +858,15 @@ update_symbols(PyObject *symbols, PyObject *scopes, goto error; } /* Handle global symbol */ - if (bound && !PySet_Contains(bound, name)) { - Py_DECREF(name); - continue; /* it's a global */ + if (bound) { + int contains = PySet_Contains(bound, name); + if (contains < 0) { + goto error; + } + if (!contains) { + Py_DECREF(name); + continue; /* it's a global */ + } } /* Propagate new free symbol up the lexical stack */ if (PyDict_SetItem(symbols, name, v_free) < 0) { |