diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 366bca44f83f16..2e86e11e140ebc 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -802,15 +802,18 @@ dummy_func( */ assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left)); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); - PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); - PyUnicode_Append(&temp, right_o); - PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); - DEAD(right); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); + /* gh-143403: It's critical to close this reference *before* + * we append. Otherwise, append can move the underlying + * unicode object, which will cause a use after free! + */ PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); DEAD(left); + PyUnicode_Append(&temp, right_o); + _Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc); + *target_local = PyStackRef_NULL; ERROR_IF(temp == NULL); res = PyStackRef_FromPyObjectSteal(temp); - *target_local = PyStackRef_NULL; } op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 3fe7a3200269c3..def627204b4b11 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4957,30 +4957,22 @@ STAT_INC(BINARY_OP, hit); assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left)); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); - PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); - stack_pointer[0] = left; - stack_pointer[1] = right; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); + PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); _PyFrame_SetStackPointer(frame, stack_pointer); PyUnicode_Append(&temp, right_o); + _Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); - PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); + *target_local = PyStackRef_NULL; if (temp == NULL) { - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(temp); - *target_local = PyStackRef_NULL; _tos_cache0 = res; _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index a1d5a98255c405..a0a1e94921b92d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -428,20 +428,22 @@ STAT_INC(BINARY_OP, hit); assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left)); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); - PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); + PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); PyUnicode_Append(&temp, right_o); + _Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); - PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); + *target_local = PyStackRef_NULL; if (temp == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(temp); - *target_local = PyStackRef_NULL; } - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); }