@@ -2459,6 +2459,24 @@ write_size_t(void *p, size_t n)
2459
2459
}
2460
2460
}
2461
2461
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
+
2462
2480
/* Let S = sizeof(size_t). The debug malloc asks for 4 * S extra bytes and
2463
2481
fills them with useful stuff, here calling the underlying malloc's result p:
2464
2482
@@ -2535,7 +2553,7 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
2535
2553
memset (p + SST + 1 , PYMEM_FORBIDDENBYTE , SST - 1 );
2536
2554
2537
2555
if (nbytes > 0 && !use_calloc ) {
2538
- memset ( data , PYMEM_CLEANBYTE , nbytes );
2556
+ fill_mem_debug ( api , data , PYMEM_CLEANBYTE , nbytes );
2539
2557
}
2540
2558
2541
2559
/* at tail, write pad (SST bytes) and serialno (SST bytes) */
@@ -2583,8 +2601,9 @@ _PyMem_DebugRawFree(void *ctx, void *p)
2583
2601
2584
2602
_PyMem_DebugCheckAddress (__func__ , api -> api_id , p );
2585
2603
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 );
2588
2607
api -> alloc .free (api -> alloc .ctx , q );
2589
2608
}
2590
2609
@@ -2604,7 +2623,6 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
2604
2623
size_t total ; /* 2 * SST + nbytes + 2 * SST */
2605
2624
size_t original_nbytes ;
2606
2625
#define ERASED_SIZE 64
2607
- uint8_t save [2 * ERASED_SIZE ]; /* A copy of erased bytes. */
2608
2626
2609
2627
_PyMem_DebugCheckAddress (__func__ , api -> api_id , p );
2610
2628
@@ -2621,9 +2639,11 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
2621
2639
#ifdef PYMEM_DEBUG_SERIALNO
2622
2640
size_t block_serialno = read_size_t (tail + SST );
2623
2641
#endif
2642
+ #ifndef Py_GIL_DISABLED
2624
2643
/* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
2625
2644
ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
2626
2645
*/
2646
+ uint8_t save [2 * ERASED_SIZE ]; /* A copy of erased bytes. */
2627
2647
if (original_nbytes <= sizeof (save )) {
2628
2648
memcpy (save , data , original_nbytes );
2629
2649
memset (data - 2 * SST , PYMEM_DEADBYTE ,
@@ -2636,6 +2656,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
2636
2656
memset (tail - ERASED_SIZE , PYMEM_DEADBYTE ,
2637
2657
ERASED_SIZE + PYMEM_DEBUG_EXTRA_BYTES - 2 * SST );
2638
2658
}
2659
+ #endif
2639
2660
2640
2661
/* Resize and add decorations. */
2641
2662
r = (uint8_t * )api -> alloc .realloc (api -> alloc .ctx , head , total );
@@ -2663,6 +2684,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
2663
2684
write_size_t (tail + SST , block_serialno );
2664
2685
#endif
2665
2686
2687
+ #ifndef Py_GIL_DISABLED
2666
2688
/* Restore saved bytes. */
2667
2689
if (original_nbytes <= sizeof (save )) {
2668
2690
memcpy (data , save , Py_MIN (nbytes , original_nbytes ));
@@ -2675,6 +2697,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
2675
2697
Py_MIN (nbytes - i , ERASED_SIZE ));
2676
2698
}
2677
2699
}
2700
+ #endif
2678
2701
2679
2702
if (r == NULL ) {
2680
2703
return NULL ;
0 commit comments