https://github.com/python/cpython/commit/1d11627ba555a365c820e1e1535a42a4f4fbd4c6
commit: 1d11627ba555a365c820e1e1535a42a4f4fbd4c6
branch: 3.14
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-10-18T19:40:43+05:30
summary:

[3.14] gh-140067: Fix memory leak in sub-interpreter creation  (GH-140111) 
(#140118)

* [3.14] gh-140067: Fix memory leak in sub-interpreter creation  (GH-140111)

Fix memory leak in sub-interpreter creation caused by overwriting of the 
previously used `_malloced` field. Now the pointer is stored in the first word 
of the memory block to avoid it being overwritten accidentally.
(cherry picked from commit 59547a251f7069dc6e08cb6082dd21872671e381)

Co-authored-by: Shamil <[email protected]>
Co-authored-by: Kumar Aditya <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-10-14-17-07-37.gh-issue-140067.ID2gOm.rst
M Include/internal/pycore_interp_structs.h
M Lib/test/test_threading.py
M Python/pystate.c

diff --git a/Include/internal/pycore_interp_structs.h 
b/Include/internal/pycore_interp_structs.h
index d1f916fa7f727c..15885b5f228c8b 100644
--- a/Include/internal/pycore_interp_structs.h
+++ b/Include/internal/pycore_interp_structs.h
@@ -768,10 +768,7 @@ 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.
-     */
+    // unused, kept for ABI compatibility
     void *_malloced;
 
     PyInterpreterState *next;
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 59db91b0ffce5e..bb51ddd38e2cad 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -1727,6 +1727,7 @@ def task():
         self.assertEqual(os.read(r_interp, 1), DONE)
 
     @cpython_only
+    @support.skip_if_sanitizer(thread=True, memory=True)
     def test_daemon_threads_fatal_error(self):
         import_module("_testcapi")
         subinterp_code = f"""if 1:
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
new file mode 100644
index 00000000000000..3c5a828101d9a8
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-14-17-07-37.gh-issue-140067.ID2gOm.rst
@@ -0,0 +1 @@
+Fix memory leak in sub-interpreter creation.
diff --git a/Python/pystate.c b/Python/pystate.c
index 9f6e961e71ae9f..7f365ea50cab7d 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -565,16 +565,19 @@ _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) + alignment - 1;
+    size_t allocsize = sizeof(PyInterpreterState) + sizeof(void *) + alignment 
- 1;
     void *mem = PyMem_RawCalloc(1, allocsize);
     if (mem == NULL) {
         return NULL;
     }
-    PyInterpreterState *interp = _Py_ALIGN_UP(mem, alignment);
-    assert(_Py_IS_ALIGNED(interp, alignment));
-    interp->_malloced = mem;
-    return interp;
+    void *ptr = _Py_ALIGN_UP((char *)mem + sizeof(void *), alignment);
+    ((void **)ptr)[-1] = mem;
+    assert(_Py_IS_ALIGNED(ptr, alignment));
+    return ptr;
 }
 
 static void
@@ -589,7 +592,7 @@ free_interpreter(PyInterpreterState *interp)
             interp->obmalloc = NULL;
         }
         assert(_Py_IS_ALIGNED(interp, _Alignof(PyInterpreterState)));
-        PyMem_RawFree(interp->_malloced);
+        PyMem_RawFree(((void **)interp)[-1]);
     }
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to