@@ -2459,6 +2459,24 @@ write_size_t(void *p, size_t n)
24592459 }
24602460}
24612461
2462+ static void
2463+ fill_mem_debug (debug_alloc_api_t * api , void * data , int c , size_t nbytes )
2464+ {
2465+ #ifdef Py_GIL_DISABLED
2466+ if (api -> api_id == 'o' ) {
2467+ // Don't overwrite the first few bytes of a PyObject allocation in the
2468+ // free-threaded build
2469+ _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
2470+ size_t debug_offset = tstate -> mimalloc .current_object_heap -> debug_offset ;
2471+ if (debug_offset < nbytes ) {
2472+ memset ((char * )data + debug_offset , c , nbytes - debug_offset );
2473+ }
2474+ return ;
2475+ }
2476+ #endif
2477+ memset (data , c , nbytes );
2478+ }
2479+
24622480/* Let S = sizeof(size_t). The debug malloc asks for 4 * S extra bytes and
24632481 fills them with useful stuff, here calling the underlying malloc's result p:
24642482
@@ -2535,7 +2553,7 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
25352553 memset (p + SST + 1 , PYMEM_FORBIDDENBYTE , SST - 1 );
25362554
25372555 if (nbytes > 0 && !use_calloc ) {
2538- memset ( data , PYMEM_CLEANBYTE , nbytes );
2556+ fill_mem_debug ( api , data , PYMEM_CLEANBYTE , nbytes );
25392557 }
25402558
25412559 /* at tail, write pad (SST bytes) and serialno (SST bytes) */
@@ -2583,8 +2601,9 @@ _PyMem_DebugRawFree(void *ctx, void *p)
25832601
25842602 _PyMem_DebugCheckAddress (__func__ , api -> api_id , p );
25852603 nbytes = read_size_t (q );
2586- nbytes += PYMEM_DEBUG_EXTRA_BYTES ;
2587- memset (q , PYMEM_DEADBYTE , nbytes );
2604+ nbytes += PYMEM_DEBUG_EXTRA_BYTES - 2 * SST ;
2605+ memset (q , PYMEM_DEADBYTE , 2 * SST );
2606+ fill_mem_debug (api , p , PYMEM_DEADBYTE , nbytes );
25882607 api -> alloc .free (api -> alloc .ctx , q );
25892608}
25902609
@@ -2604,7 +2623,6 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
26042623 size_t total ; /* 2 * SST + nbytes + 2 * SST */
26052624 size_t original_nbytes ;
26062625#define ERASED_SIZE 64
2607- uint8_t save [2 * ERASED_SIZE ]; /* A copy of erased bytes. */
26082626
26092627 _PyMem_DebugCheckAddress (__func__ , api -> api_id , p );
26102628
@@ -2621,9 +2639,11 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
26212639#ifdef PYMEM_DEBUG_SERIALNO
26222640 size_t block_serialno = read_size_t (tail + SST );
26232641#endif
2642+ #ifndef Py_GIL_DISABLED
26242643 /* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
26252644 ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
26262645 */
2646+ uint8_t save [2 * ERASED_SIZE ]; /* A copy of erased bytes. */
26272647 if (original_nbytes <= sizeof (save )) {
26282648 memcpy (save , data , original_nbytes );
26292649 memset (data - 2 * SST , PYMEM_DEADBYTE ,
@@ -2636,6 +2656,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
26362656 memset (tail - ERASED_SIZE , PYMEM_DEADBYTE ,
26372657 ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST );
26382658 }
2659+ #endif
26392660
26402661 /* Resize and add decorations. */
26412662 r = (uint8_t * )api -> alloc .realloc (api -> alloc .ctx , head , total );
@@ -2663,6 +2684,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
26632684 write_size_t (tail + SST , block_serialno );
26642685#endif
26652686
2687+ #ifndef Py_GIL_DISABLED
26662688 /* Restore saved bytes. */
26672689 if (original_nbytes <= sizeof (save )) {
26682690 memcpy (data , save , Py_MIN (nbytes , original_nbytes ));
@@ -2675,6 +2697,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
26752697 Py_MIN (nbytes - i , ERASED_SIZE ));
26762698 }
26772699 }
2700+ #endif
26782701
26792702 if (r == NULL ) {
26802703 return NULL ;
0 commit comments