mirror of https://github.com/python/cpython
gh-115491: Keep some fields valid across allocations in obmalloc (free-threading) (#115745)
This commit is contained in:
parent
87a65a5bd4
commit
347acded84
|
@ -299,13 +299,13 @@ _Py_DecRef(PyObject *o)
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
# ifdef Py_REF_DEBUG
|
# ifdef Py_REF_DEBUG
|
||||||
static inline int
|
static int
|
||||||
is_shared_refcnt_dead(Py_ssize_t shared)
|
is_dead(PyObject *o)
|
||||||
{
|
{
|
||||||
# if SIZEOF_SIZE_T == 8
|
# if SIZEOF_SIZE_T == 8
|
||||||
return shared == (Py_ssize_t)0xDDDDDDDDDDDDDDDD;
|
return (uintptr_t)o->ob_type == 0xDDDDDDDDDDDDDDDD;
|
||||||
# else
|
# else
|
||||||
return shared == (Py_ssize_t)0xDDDDDDDD;
|
return (uintptr_t)o->ob_type == 0xDDDDDDDD;
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
@ -335,8 +335,8 @@ _Py_DecRefSharedDebug(PyObject *o, const char *filename, int lineno)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Py_REF_DEBUG
|
#ifdef Py_REF_DEBUG
|
||||||
if ((_Py_REF_IS_MERGED(new_shared) && new_shared < 0) ||
|
if ((new_shared < 0 && _Py_REF_IS_MERGED(new_shared)) ||
|
||||||
is_shared_refcnt_dead(shared))
|
(should_queue && is_dead(o)))
|
||||||
{
|
{
|
||||||
_Py_NegativeRefcount(filename, lineno, o);
|
_Py_NegativeRefcount(filename, lineno, o);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2459,6 +2459,24 @@ write_size_t(void *p, size_t n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_mem_debug(debug_alloc_api_t *api, void *data, int c, size_t nbytes)
|
||||||
|
{
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
if (api->api_id == 'o') {
|
||||||
|
// Don't overwrite the first few bytes of a PyObject allocation in the
|
||||||
|
// free-threaded build
|
||||||
|
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
|
||||||
|
size_t debug_offset = tstate->mimalloc.current_object_heap->debug_offset;
|
||||||
|
if (debug_offset < nbytes) {
|
||||||
|
memset((char *)data + debug_offset, c, nbytes - debug_offset);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
memset(data, c, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
/* Let S = sizeof(size_t). The debug malloc asks for 4 * S extra bytes and
|
/* Let S = sizeof(size_t). The debug malloc asks for 4 * S extra bytes and
|
||||||
fills them with useful stuff, here calling the underlying malloc's result p:
|
fills them with useful stuff, here calling the underlying malloc's result p:
|
||||||
|
|
||||||
|
@ -2535,7 +2553,7 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
|
||||||
memset(p + SST + 1, PYMEM_FORBIDDENBYTE, SST-1);
|
memset(p + SST + 1, PYMEM_FORBIDDENBYTE, SST-1);
|
||||||
|
|
||||||
if (nbytes > 0 && !use_calloc) {
|
if (nbytes > 0 && !use_calloc) {
|
||||||
memset(data, PYMEM_CLEANBYTE, nbytes);
|
fill_mem_debug(api, data, PYMEM_CLEANBYTE, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* at tail, write pad (SST bytes) and serialno (SST bytes) */
|
/* at tail, write pad (SST bytes) and serialno (SST bytes) */
|
||||||
|
@ -2583,8 +2601,9 @@ _PyMem_DebugRawFree(void *ctx, void *p)
|
||||||
|
|
||||||
_PyMem_DebugCheckAddress(__func__, api->api_id, p);
|
_PyMem_DebugCheckAddress(__func__, api->api_id, p);
|
||||||
nbytes = read_size_t(q);
|
nbytes = read_size_t(q);
|
||||||
nbytes += PYMEM_DEBUG_EXTRA_BYTES;
|
nbytes += PYMEM_DEBUG_EXTRA_BYTES - 2*SST;
|
||||||
memset(q, PYMEM_DEADBYTE, nbytes);
|
memset(q, PYMEM_DEADBYTE, 2*SST);
|
||||||
|
fill_mem_debug(api, p, PYMEM_DEADBYTE, nbytes);
|
||||||
api->alloc.free(api->alloc.ctx, q);
|
api->alloc.free(api->alloc.ctx, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2604,7 +2623,6 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||||
size_t total; /* 2 * SST + nbytes + 2 * SST */
|
size_t total; /* 2 * SST + nbytes + 2 * SST */
|
||||||
size_t original_nbytes;
|
size_t original_nbytes;
|
||||||
#define ERASED_SIZE 64
|
#define ERASED_SIZE 64
|
||||||
uint8_t save[2*ERASED_SIZE]; /* A copy of erased bytes. */
|
|
||||||
|
|
||||||
_PyMem_DebugCheckAddress(__func__, api->api_id, p);
|
_PyMem_DebugCheckAddress(__func__, api->api_id, p);
|
||||||
|
|
||||||
|
@ -2621,9 +2639,11 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||||
#ifdef PYMEM_DEBUG_SERIALNO
|
#ifdef PYMEM_DEBUG_SERIALNO
|
||||||
size_t block_serialno = read_size_t(tail + SST);
|
size_t block_serialno = read_size_t(tail + SST);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
/* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
|
/* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
|
||||||
ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
|
ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
|
||||||
*/
|
*/
|
||||||
|
uint8_t save[2*ERASED_SIZE]; /* A copy of erased bytes. */
|
||||||
if (original_nbytes <= sizeof(save)) {
|
if (original_nbytes <= sizeof(save)) {
|
||||||
memcpy(save, data, original_nbytes);
|
memcpy(save, data, original_nbytes);
|
||||||
memset(data - 2 * SST, PYMEM_DEADBYTE,
|
memset(data - 2 * SST, PYMEM_DEADBYTE,
|
||||||
|
@ -2636,6 +2656,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||||
memset(tail - ERASED_SIZE, PYMEM_DEADBYTE,
|
memset(tail - ERASED_SIZE, PYMEM_DEADBYTE,
|
||||||
ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST);
|
ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Resize and add decorations. */
|
/* Resize and add decorations. */
|
||||||
r = (uint8_t *)api->alloc.realloc(api->alloc.ctx, head, total);
|
r = (uint8_t *)api->alloc.realloc(api->alloc.ctx, head, total);
|
||||||
|
@ -2663,6 +2684,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||||
write_size_t(tail + SST, block_serialno);
|
write_size_t(tail + SST, block_serialno);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_GIL_DISABLED
|
||||||
/* Restore saved bytes. */
|
/* Restore saved bytes. */
|
||||||
if (original_nbytes <= sizeof(save)) {
|
if (original_nbytes <= sizeof(save)) {
|
||||||
memcpy(data, save, Py_MIN(nbytes, original_nbytes));
|
memcpy(data, save, Py_MIN(nbytes, original_nbytes));
|
||||||
|
@ -2675,6 +2697,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||||
Py_MIN(nbytes - i, ERASED_SIZE));
|
Py_MIN(nbytes - i, ERASED_SIZE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (r == NULL) {
|
if (r == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue