@@ -1418,7 +1418,7 @@ static void *
14181418_PyMem_DebugRawAlloc (int use_calloc , void * ctx , size_t nbytes )
14191419{
14201420 debug_alloc_api_t * api = (debug_alloc_api_t * )ctx ;
1421- uint8_t * p ; /* base address of malloc'epad d block */
1421+ uint8_t * p ; /* base address of malloc'ed pad block */
14221422 uint8_t * data ; /* p + 2*SST == pointer to data bytes */
14231423 uint8_t * tail ; /* data + nbytes == pointer to tail pad bytes */
14241424 size_t total ; /* 2 * SST + nbytes + 2 * SST */
@@ -1516,45 +1516,83 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
15161516 }
15171517
15181518 debug_alloc_api_t * api = (debug_alloc_api_t * )ctx ;
1519- uint8_t * q ; /* base address of malloc'epad d block */
1520- uint8_t * data ; /* p + 2*SST == pointer to data bytes */
1519+ uint8_t * head ; /* base address of malloc'ed pad block */
1520+ uint8_t * data ; /* pointer to data bytes */
1521+ uint8_t * r ;
15211522 uint8_t * tail ; /* data + nbytes == pointer to tail pad bytes */
15221523 size_t total ; /* 2 * SST + nbytes + 2 * SST */
15231524 size_t original_nbytes ;
1524- int i ;
1525+ size_t serialno ;
1526+ #define ERASED_SIZE 64
1527+ uint8_t save [2 * ERASED_SIZE ]; /* A copy of erased bytes. */
15251528
15261529 _PyMem_DebugCheckAddress (api -> api_id , p );
15271530
1528- q = (uint8_t * )p ;
1529- original_nbytes = read_size_t (q - 2 * SST );
1531+ data = (uint8_t * )p ;
1532+ head = data - 2 * SST ;
1533+ original_nbytes = read_size_t (head );
15301534 if (nbytes > (size_t )PY_SSIZE_T_MAX - 4 * SST ) {
15311535 /* integer overflow: can't represent total as a Py_ssize_t */
15321536 return NULL ;
15331537 }
15341538 total = nbytes + 4 * SST ;
15351539
1536- /* Resize and add decorations. */
1537- q = (uint8_t * )api -> alloc .realloc (api -> alloc .ctx , q - 2 * SST , total );
1538- if (q == NULL ) {
1539- return NULL ;
1540+ tail = data + original_nbytes ;
1541+ serialno = read_size_t (tail + SST );
1542+ /* Mark the header, the trailer, ERASED_SIZE bytes at the begin and
1543+ ERASED_SIZE bytes at the end as dead and save the copy of erased bytes.
1544+ */
1545+ if (original_nbytes <= sizeof (save )) {
1546+ memcpy (save , data , original_nbytes );
1547+ memset (data - 2 * SST , DEADBYTE , original_nbytes + 4 * SST );
1548+ }
1549+ else {
1550+ memcpy (save , data , ERASED_SIZE );
1551+ memset (head , DEADBYTE , ERASED_SIZE + 2 * SST );
1552+ memcpy (& save [ERASED_SIZE ], tail - ERASED_SIZE , ERASED_SIZE );
1553+ memset (tail - ERASED_SIZE , DEADBYTE , ERASED_SIZE + 2 * SST );
15401554 }
15411555
1542- bumpserialno ();
1543- write_size_t (q , nbytes );
1544- assert (q [SST ] == (uint8_t )api -> api_id );
1545- for (i = 1 ; i < SST ; ++ i ) {
1546- assert (q [SST + i ] == FORBIDDENBYTE );
1556+ /* Resize and add decorations. */
1557+ r = (uint8_t * )api -> alloc .realloc (api -> alloc .ctx , head , total );
1558+ if (r == NULL ) {
1559+ nbytes = original_nbytes ;
1560+ }
1561+ else {
1562+ head = r ;
1563+ bumpserialno ();
1564+ serialno = _PyRuntime .mem .serialno ;
15471565 }
1548- data = q + 2 * SST ;
1566+
1567+ write_size_t (head , nbytes );
1568+ head [SST ] = (uint8_t )api -> api_id ;
1569+ memset (head + SST + 1 , FORBIDDENBYTE , SST - 1 );
1570+ data = head + 2 * SST ;
15491571
15501572 tail = data + nbytes ;
15511573 memset (tail , FORBIDDENBYTE , SST );
1552- write_size_t (tail + SST , _PyRuntime .mem .serialno );
1574+ write_size_t (tail + SST , serialno );
1575+
1576+ /* Restore saved bytes. */
1577+ if (original_nbytes <= sizeof (save )) {
1578+ memcpy (data , save , Py_MIN (nbytes , original_nbytes ));
1579+ }
1580+ else {
1581+ size_t i = original_nbytes - ERASED_SIZE ;
1582+ memcpy (data , save , Py_MIN (nbytes , ERASED_SIZE ));
1583+ if (nbytes > i ) {
1584+ memcpy (data + i , & save [ERASED_SIZE ],
1585+ Py_MIN (nbytes - i , ERASED_SIZE ));
1586+ }
1587+ }
1588+
1589+ if (r == NULL ) {
1590+ return NULL ;
1591+ }
15531592
15541593 if (nbytes > original_nbytes ) {
15551594 /* growing: mark new extra memory clean */
1556- memset (data + original_nbytes , CLEANBYTE ,
1557- nbytes - original_nbytes );
1595+ memset (data + original_nbytes , CLEANBYTE , nbytes - original_nbytes );
15581596 }
15591597
15601598 return data ;
0 commit comments