https://github.com/python/cpython/commit/427e7fc099e61d9a3d1f04e2fbde8b749e5fcf0a commit: 427e7fc099e61d9a3d1f04e2fbde8b749e5fcf0a branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-04-19T11:03:06+02:00 summary:
gh-132399: ensure correct alignment of `PyInterpreterState` (#132428) files: M Include/internal/pycore_interp_structs.h M Python/pystate.c diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 573b56a57e1d54..9ac4b4630abd3f 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -754,6 +754,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/Python/pystate.c b/Python/pystate.c index ee35f0fa945f8b..aba558279a657d 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -569,11 +569,19 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) return _PyStatus_OK(); } - static PyInterpreterState * alloc_interpreter(void) { - return PyMem_RawCalloc(1, sizeof(PyInterpreterState)); + size_t alignment = _Alignof(PyInterpreterState); + size_t allocsize = sizeof(PyInterpreterState) + 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; } static void @@ -587,12 +595,15 @@ free_interpreter(PyInterpreterState *interp) PyMem_RawFree(interp->obmalloc); interp->obmalloc = NULL; } - PyMem_RawFree(interp); + assert(_Py_IS_ALIGNED(interp, _Alignof(PyInterpreterState))); + PyMem_RawFree(interp->_malloced); } } + #ifndef NDEBUG static inline int check_interpreter_whence(long); #endif + /* Get the interpreter state to a minimal consistent state. Further init happens in pylifecycle.c before it can be used. All fields not initialized here are expected to be zeroed out, _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com