diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index badc97808c6132..2124e76514f1af 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -769,6 +769,12 @@ struct _is { * and should be placed at the beginning. */ struct _ceval_state ceval; + /* This structure is carefully allocated so that it's correctly aligned + * to avoid undefined behaviors during LOAD and STORE. The '_malloced' + * field stores the allocated pointer address that will later be freed. + */ + void *_malloced; + PyInterpreterState *next; int64_t id; diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-14-17-07-37.gh-issue-140067.ID2gOm.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-14-17-07-37.gh-issue-140067.ID2gOm.rst deleted file mode 100644 index 3c5a828101d9a8..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-14-17-07-37.gh-issue-140067.ID2gOm.rst +++ /dev/null @@ -1 +0,0 @@ -Fix memory leak in sub-interpreter creation. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index c519485c1cc74c..a73bfff340ce48 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1469,14 +1469,14 @@ bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix) /*[clinic input] bytearray.resize size: Py_ssize_t - New size to resize to.. + New size to resize to. / Resize the internal buffer of bytearray to len. [clinic start generated code]*/ static PyObject * bytearray_resize_impl(PyByteArrayObject *self, Py_ssize_t size) -/*[clinic end generated code: output=f73524922990b2d9 input=75fd4d17c4aa47d3]*/ +/*[clinic end generated code: output=f73524922990b2d9 input=6c9a260ca7f72071]*/ { Py_ssize_t start_size = PyByteArray_GET_SIZE(self); int result = PyByteArray_Resize((PyObject *)self, size); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index ffb45ade11f6dc..6f13865177dde5 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -599,7 +599,7 @@ PyDoc_STRVAR(bytearray_resize__doc__, "Resize the internal buffer of bytearray to len.\n" "\n" " size\n" -" New size to resize to.."); +" New size to resize to."); #define BYTEARRAY_RESIZE_METHODDEF \ {"resize", (PyCFunction)bytearray_resize, METH_O, bytearray_resize__doc__}, @@ -1796,4 +1796,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl((PyByteArrayObject *)self); } -/*[clinic end generated code: output=be6d28193bc96a2c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fdfe41139c91e409 input=a9049054013a1b77]*/ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9398bcb29c83e4..29233c1959c4d0 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -81,7 +81,7 @@ class object "PyObject *" "&PyBaseObject_Type" #define END_TYPE_DICT_LOCK() Py_END_CRITICAL_SECTION2() -#ifdef Py_DEBUG +#ifndef NDEBUG // Return true if the world is currently stopped. static bool types_world_is_stopped(void) diff --git a/Python/pystate.c b/Python/pystate.c index bf6e4e56e6df87..dbed609f29aa07 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -457,19 +457,16 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) static PyInterpreterState * alloc_interpreter(void) { - // Aligned allocation for PyInterpreterState. - // the first word of the memory block is used to store - // the original pointer to be used later to free the memory. size_t alignment = _Alignof(PyInterpreterState); - size_t allocsize = sizeof(PyInterpreterState) + sizeof(void *) + alignment - 1; + size_t allocsize = sizeof(PyInterpreterState) + alignment - 1; void *mem = PyMem_RawCalloc(1, allocsize); if (mem == NULL) { return NULL; } - void *ptr = _Py_ALIGN_UP((char *)mem + sizeof(void *), alignment); - ((void **)ptr)[-1] = mem; - assert(_Py_IS_ALIGNED(ptr, alignment)); - return ptr; + PyInterpreterState *interp = _Py_ALIGN_UP(mem, alignment); + assert(_Py_IS_ALIGNED(interp, alignment)); + interp->_malloced = mem; + return interp; } static void @@ -484,7 +481,7 @@ free_interpreter(PyInterpreterState *interp) interp->obmalloc = NULL; } assert(_Py_IS_ALIGNED(interp, _Alignof(PyInterpreterState))); - PyMem_RawFree(((void **)interp)[-1]); + PyMem_RawFree(interp->_malloced); } }