summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorTomasz Pytel <tompytel@gmail.com>2025-04-04 15:23:40 (GMT)
committerGitHub <noreply@github.com>2025-04-04 15:23:40 (GMT)
commit900dc2b0340fdd77314b69780dbe1397067b2104 (patch)
tree7553064d301a731f0a0a23302e71faed2392f9bb /Python
parentd8986b7f5e91f6aedf33da29d46c094a104e1025 (diff)
downloadcpython-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.c18
-rw-r--r--Python/symtable.c27
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;