From 089c19b9268687355697d1c371a28867343f0ca1 Mon Sep 17 00:00:00 2001 From: A0su Date: Wed, 25 Mar 2026 22:03:26 -0500 Subject: [PATCH 1/2] fix null derefs, missing decrefs, and unchecked returns from bug report --- Python/assemble.c | 1 + Python/codegen.c | 18 +++++++++++++----- Python/compile.c | 4 ++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Python/assemble.c b/Python/assemble.c index 7c08488092de63..3df959c3634195 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -418,6 +418,7 @@ assemble_emit_instr(struct assembler *a, instruction *instr) int size = instr_size(instr); if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) { if (len > PY_SSIZE_T_MAX / 2) { + PyErr_NoMemory(); return ERROR; } RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2)); diff --git a/Python/codegen.c b/Python/codegen.c index d300d77e0f73b0..24118186e810c5 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -667,8 +667,8 @@ codegen_unwind_fblock_stack(compiler *c, location *ploc, _PyCompile_PopFBlock(c, top->fb_type, top->fb_block); RETURN_IF_ERROR(codegen_unwind_fblock(c, ploc, ©, preserve_tos)); RETURN_IF_ERROR(codegen_unwind_fblock_stack(c, ploc, preserve_tos, loop)); - _PyCompile_PushFBlock(c, copy.fb_loc, copy.fb_type, copy.fb_block, - copy.fb_exit, copy.fb_datum); + RETURN_IF_ERROR(_PyCompile_PushFBlock(c, copy.fb_loc, copy.fb_type, copy.fb_block, + copy.fb_exit, copy.fb_datum)); return SUCCESS; } @@ -715,10 +715,14 @@ codegen_setup_annotations_scope(compiler *c, location loc, // if .format > VALUE_WITH_FAKE_GLOBALS: raise NotImplementedError PyObject *value_with_fake_globals = PyLong_FromLong(_Py_ANNOTATE_FORMAT_VALUE_WITH_FAKE_GLOBALS); + if (value_with_fake_globals == NULL) { + return ERROR; + } + assert(!SYMTABLE_ENTRY(c)->ste_has_docstring); _Py_DECLARE_STR(format, ".format"); ADDOP_I(c, loc, LOAD_FAST, 0); - ADDOP_LOAD_CONST(c, loc, value_with_fake_globals); + ADDOP_LOAD_CONST_NEW(c, loc, value_with_fake_globals); // macro handles decref of value_with_fake_globals ADDOP_I(c, loc, COMPARE_OP, (Py_GT << 5) | compare_masks[Py_GT]); NEW_JUMP_TARGET_LABEL(c, body); ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, body); @@ -816,7 +820,7 @@ codegen_deferred_annotations_body(compiler *c, location loc, VISIT(c, expr, st->v.AnnAssign.annotation); ADDOP_I(c, LOC(st), COPY, 2); - ADDOP_LOAD_CONST_NEW(c, LOC(st), mangled); + ADDOP_LOAD_CONST_NEW(c, LOC(st), mangled); // macro handles decref of mangle // stack now contains ADDOP(c, loc, STORE_SUBSCR); // stack now contains @@ -3279,7 +3283,11 @@ codegen_nameop(compiler *c, location loc, } int scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled); - RETURN_IF_ERROR(scope); + if (scope == -1) { + Py_DECREF(mangled); + return ERROR; + } + _PyCompile_optype optype; Py_ssize_t arg = 0; if (_PyCompile_ResolveNameop(c, mangled, scope, &optype, &arg) < 0) { diff --git a/Python/compile.c b/Python/compile.c index 4cf178b06ae11d..365b118cc71b44 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1100,18 +1100,22 @@ _PyCompile_TweakInlinedComprehensionScopes(compiler *c, location loc, assert(orig == NULL || orig == Py_True || orig == Py_False); if (orig != Py_True) { if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) { + Py_XDECREF(orig); return ERROR; } if (state->fast_hidden == NULL) { state->fast_hidden = PySet_New(NULL); if (state->fast_hidden == NULL) { + Py_XDECREF(orig); return ERROR; } } if (PySet_Add(state->fast_hidden, k) < 0) { + Py_XDECREF(orig); return ERROR; } } + Py_XDECREF(orig); } } } From aff400a0b6ffe5e95caf56e3839019674f6c0682 Mon Sep 17 00:00:00 2001 From: A0su Date: Wed, 25 Mar 2026 22:41:11 -0500 Subject: [PATCH 2/2] add disclaimer for leaks in codegen_deferred_annotations_body --- Python/codegen.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Python/codegen.c b/Python/codegen.c index 24118186e810c5..6c5705b22da109 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -798,6 +798,9 @@ codegen_deferred_annotations_body(compiler *c, location loc, if (!mangled) { return ERROR; } + // NOTE: ref of mangled can be leaked on ADDOP* and VISIT macros due to early returns + // fixing would require an overhaul of these macros + PyObject *cond_index = PyList_GET_ITEM(conditional_annotation_indices, i); assert(PyLong_CheckExact(cond_index)); long idx = PyLong_AS_LONG(cond_index);