diff options
| author | Tomasz Pytel <tompytel@gmail.com> | 2025-04-04 15:23:40 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-04 15:23:40 (GMT) |
| commit | 900dc2b0340fdd77314b69780dbe1397067b2104 (patch) | |
| tree | 7553064d301a731f0a0a23302e71faed2392f9bb /Python | |
| parent | d8986b7f5e91f6aedf33da29d46c094a104e1025 (diff) | |
| download | cpython-900dc2b0340fdd77314b69780dbe1397067b2104.zip cpython-900dc2b0340fdd77314b69780dbe1397067b2104.tar.gz cpython-900dc2b0340fdd77314b69780dbe1397067b2104.tar.bz2 | |
[3.13] gh-128632: fix segfault on nested __classdict__ type param (GH-128744) (#132085)
(cherry picked from commit 891c61c1fa480928dd60cce8bbc8764630c95025)
Co-authored-by: Tomasz Pytel <tompytel@gmail.com>
Diffstat (limited to 'Python')
| -rw-r--r-- | Python/assemble.c | 18 | ||||
| -rw-r--r-- | Python/symtable.c | 27 |
2 files changed, 32 insertions, 13 deletions
diff --git a/Python/assemble.c b/Python/assemble.c index 671bc7c..98816ae 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -503,7 +503,7 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); // This counter mirrors the fix done in fix_cell_offsets(). - int numdropped = 0; + int numdropped = 0, cellvar_offset = -1; pos = 0; while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) { int has_name = PyDict_Contains(umd->u_varnames, k); @@ -514,14 +514,14 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, continue; } - int offset = PyLong_AsInt(v); - if (offset == -1 && PyErr_Occurred()) { + cellvar_offset = PyLong_AsInt(v); + if (cellvar_offset == -1 && PyErr_Occurred()) { return ERROR; } - assert(offset >= 0); - offset += nlocals - numdropped; - assert(offset < nlocalsplus); - _Py_set_localsplus_info(offset, k, CO_FAST_CELL, names, kinds); + assert(cellvar_offset >= 0); + cellvar_offset += nlocals - numdropped; + assert(cellvar_offset < nlocalsplus); + _Py_set_localsplus_info(cellvar_offset, k, CO_FAST_CELL, names, kinds); } pos = 0; @@ -533,6 +533,10 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, assert(offset >= 0); offset += nlocals - numdropped; assert(offset < nlocalsplus); + /* XXX If the assertion below fails it is most likely because a freevar + was added to u_freevars with the wrong index due to not taking into + account cellvars already present, see gh-128632. */ + assert(offset > cellvar_offset); _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds); } return SUCCESS; diff --git a/Python/symtable.c b/Python/symtable.c index 65dcf67..5322c5e 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -2292,12 +2292,27 @@ symtable_visit_expr(struct symtable *st, expr_ty e) static int symtable_visit_type_param_bound_or_default( struct symtable *st, expr_ty e, identifier name, - void *key, const char *ste_scope_info) + type_param_ty tp, const char *ste_scope_info) { + if (_PyUnicode_Equal(name, &_Py_ID(__classdict__))) { + + PyObject *error_msg = PyUnicode_FromFormat("reserved name '%U' cannot be " + "used for type parameter", name); + PyErr_SetObject(PyExc_SyntaxError, error_msg); + Py_DECREF(error_msg); + PyErr_RangedSyntaxLocationObject(st->st_filename, + tp->lineno, + tp->col_offset + 1, + tp->end_lineno, + tp->end_col_offset + 1); + return 0; + } + if (e) { int is_in_class = st->st_cur->ste_can_see_class_scope; - if (!symtable_enter_block(st, name, TypeVariableBlock, key, LOCATION(e))) + if (!symtable_enter_block(st, name, TypeVariableBlock, (void *)tp, LOCATION(e))) { return 0; + } st->st_cur->ste_can_see_class_scope = is_in_class; if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(e))) { @@ -2341,12 +2356,12 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp) // The only requirement for the key is that it is unique and it matches the logic in // compile.c where the scope is retrieved. if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVar.bound, tp->v.TypeVar.name, - (void *)tp, ste_scope_info)) { + tp, ste_scope_info)) { VISIT_QUIT(st, 0); } if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVar.default_value, tp->v.TypeVar.name, - (void *)((uintptr_t)tp + 1), "a TypeVar default")) { + (type_param_ty)((uintptr_t)tp + 1), "a TypeVar default")) { VISIT_QUIT(st, 0); } break; @@ -2356,7 +2371,7 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp) } if (!symtable_visit_type_param_bound_or_default(st, tp->v.TypeVarTuple.default_value, tp->v.TypeVarTuple.name, - (void *)tp, "a TypeVarTuple default")) { + tp, "a TypeVarTuple default")) { VISIT_QUIT(st, 0); } break; @@ -2366,7 +2381,7 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp) } if (!symtable_visit_type_param_bound_or_default(st, tp->v.ParamSpec.default_value, tp->v.ParamSpec.name, - (void *)tp, "a ParamSpec default")) { + tp, "a ParamSpec default")) { VISIT_QUIT(st, 0); } break; |
