From 4fd31ae442b2276570e18cb3df1a000fe3fc4049 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 28 Aug 2026 22:01:47 +0100 Subject: [PATCH] gh-156466: fix cleanup on error in codegen_class_body (GH-156507) (cherry picked from commit 683ef4082d374eb26c1ead33f8fd989eeadc742d) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> --- Python/codegen.c | 50 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/Python/codegen.c b/Python/codegen.c index 0587a81491353c..9649bad4b3dd09 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -303,19 +303,23 @@ codegen_addop_load_const(compiler *c, location loc, PyObject *o) #define ADDOP_LOAD_CONST_IN_SCOPE(C, LOC, O) \ RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_load_const((C), (LOC), (O))) +static int +codegen_addop_load_const_new(compiler *c, location loc, PyObject *o) +{ + if (o == NULL) { + return ERROR; + } + int ret = codegen_addop_load_const(c, loc, o); + Py_DECREF(o); + return ret; +} + /* Same as ADDOP_LOAD_CONST, but steals a reference. */ -#define ADDOP_LOAD_CONST_NEW(C, LOC, O) \ - do { \ - PyObject *__new_const = (O); \ - if (__new_const == NULL) { \ - return ERROR; \ - } \ - if (codegen_addop_load_const((C), (LOC), __new_const) < 0) { \ - Py_DECREF(__new_const); \ - return ERROR; \ - } \ - Py_DECREF(__new_const); \ - } while (0) +#define ADDOP_LOAD_CONST_NEW(C, LOC, O) \ + RETURN_IF_ERROR(codegen_addop_load_const_new((C), (LOC), (O))) + +#define ADDOP_LOAD_CONST_NEW_IN_SCOPE(C, LOC, O) \ + RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_load_const_new((C), (LOC), (O))) static int codegen_addop_o(compiler *c, location loc, @@ -1542,16 +1546,16 @@ codegen_class_body(compiler *c, stmt_ty s, int firstlineno) RETURN_IF_ERROR_IN_SCOPE(c, codegen_nameop(c, loc, &_Py_ID(__name__), Load)); /* ... and store it as __module__ */ RETURN_IF_ERROR_IN_SCOPE(c, codegen_nameop(c, loc, &_Py_ID(__module__), Store)); - ADDOP_LOAD_CONST(c, loc, QUALNAME(c)); + ADDOP_LOAD_CONST_IN_SCOPE(c, loc, QUALNAME(c)); RETURN_IF_ERROR_IN_SCOPE(c, codegen_nameop(c, loc, &_Py_ID(__qualname__), Store)); - ADDOP_LOAD_CONST_NEW(c, loc, PyLong_FromLong(METADATA(c)->u_firstlineno)); + ADDOP_LOAD_CONST_NEW_IN_SCOPE(c, loc, PyLong_FromLong(METADATA(c)->u_firstlineno)); RETURN_IF_ERROR_IN_SCOPE(c, codegen_nameop(c, loc, &_Py_ID(__firstlineno__), Store)); asdl_type_param_seq *type_params = s->v.ClassDef.type_params; if (asdl_seq_LEN(type_params) > 0) { RETURN_IF_ERROR_IN_SCOPE(c, codegen_set_type_params_in_class(c, loc)); } if (SYMTABLE_ENTRY(c)->ste_needs_classdict) { - ADDOP(c, loc, LOAD_LOCALS); + ADDOP_IN_SCOPE(c, loc, LOAD_LOCALS); // We can't use codegen_nameop here because we need to generate a // STORE_DEREF in a class namespace, and codegen_nameop() won't do @@ -1564,13 +1568,7 @@ codegen_class_body(compiler *c, stmt_ty s, int firstlineno) } /* compile the body proper */ RETURN_IF_ERROR_IN_SCOPE(c, codegen_body(c, loc, s->v.ClassDef.body, false)); - PyObject *static_attributes = _PyCompile_StaticAttributesAsTuple(c); - if (static_attributes == NULL) { - _PyCompile_ExitScope(c); - return ERROR; - } - ADDOP_LOAD_CONST(c, NO_LOCATION, static_attributes); - Py_CLEAR(static_attributes); + ADDOP_LOAD_CONST_NEW_IN_SCOPE(c, NO_LOCATION, _PyCompile_StaticAttributesAsTuple(c)); RETURN_IF_ERROR_IN_SCOPE( c, codegen_nameop(c, NO_LOCATION, &_Py_ID(__static_attributes__), Store)); /* The following code is artificial */ @@ -1579,7 +1577,7 @@ codegen_class_body(compiler *c, stmt_ty s, int firstlineno) /* Store __classdictcell__ into class namespace */ int i = _PyCompile_LookupCellvar(c, &_Py_ID(__classdict__)); RETURN_IF_ERROR_IN_SCOPE(c, i); - ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i); + ADDOP_I_IN_SCOPE(c, NO_LOCATION, LOAD_CLOSURE, i); RETURN_IF_ERROR_IN_SCOPE( c, codegen_nameop(c, NO_LOCATION, &_Py_ID(__classdictcell__), Store)); } @@ -1588,14 +1586,14 @@ codegen_class_body(compiler *c, stmt_ty s, int firstlineno) /* Store __classcell__ into class namespace & return it */ int i = _PyCompile_LookupCellvar(c, &_Py_ID(__class__)); RETURN_IF_ERROR_IN_SCOPE(c, i); - ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i); - ADDOP_I(c, NO_LOCATION, COPY, 1); + ADDOP_I_IN_SCOPE(c, NO_LOCATION, LOAD_CLOSURE, i); + ADDOP_I_IN_SCOPE(c, NO_LOCATION, COPY, 1); RETURN_IF_ERROR_IN_SCOPE( c, codegen_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store)); } else { /* No methods referenced __class__, so just return None */ - ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); + ADDOP_LOAD_CONST_IN_SCOPE(c, NO_LOCATION, Py_None); } ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE); /* create the code object */