diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 1485172102..359ff6583b 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1460,11 +1460,13 @@ static void * _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) { debug_alloc_api_t *api = (debug_alloc_api_t *)ctx; - uint8_t *q = (uint8_t *)p; + uint8_t *q = (uint8_t *)p, *r; uint8_t *tail; size_t total; /* nbytes + 4*SST */ size_t original_nbytes; - int i; +#define ERASED_SIZE 8 + /* A copy of erased bytes. */ + uint8_t save[2*ERASED_SIZE]; if (p == NULL) return _PyMem_DebugRawAlloc(0, ctx, nbytes); @@ -1477,21 +1479,53 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) /* overflow: can't represent total as a Py_ssize_t */ return NULL; + tail = q + original_nbytes; + /* 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. + */ + if (original_nbytes <= 2*ERASED_SIZE) { + memcpy(save, q, original_nbytes); + memset(q - 2*SST, DEADBYTE, original_nbytes + 4*SST); + } + else { + memcpy(save, q, ERASED_SIZE); + memset(q - 2*SST, DEADBYTE, ERASED_SIZE + 2*SST); + memcpy(&save[ERASED_SIZE], tail - ERASED_SIZE, ERASED_SIZE); + memset(tail - ERASED_SIZE, DEADBYTE, ERASED_SIZE + 2*SST); + } + /* Resize and add decorations. */ - q = (uint8_t *)api->alloc.realloc(api->alloc.ctx, q - 2*SST, total); - if (q == NULL) - return NULL; + r = (uint8_t *)api->alloc.realloc(api->alloc.ctx, q - 2*SST, total); + if (r != NULL) { + q = r; + } write_size_t(q, nbytes); - assert(q[SST] == (uint8_t)api->api_id); - for (i = 1; i < SST; ++i) - assert(q[SST + i] == FORBIDDENBYTE); + q[SST] = (uint8_t)api->api_id; + memset(q + SST + 1, FORBIDDENBYTE, SST-1); q += 2*SST; tail = q + nbytes; memset(tail, FORBIDDENBYTE, SST); write_size_t(tail + SST, _PyRuntime.mem.serialno); + /* Restore saved bytes. */ + if (original_nbytes <= 2*ERASED_SIZE) { + memcpy(q, save, Py_MIN(nbytes, original_nbytes)); + } + else { + if (nbytes > original_nbytes - ERASED_SIZE) { + memcpy(q + original_nbytes - ERASED_SIZE, &save[ERASED_SIZE], + Py_MIN(nbytes - original_nbytes + ERASED_SIZE, ERASED_SIZE)); + } + memcpy(q, save, Py_MIN(nbytes, ERASED_SIZE)); + } + _PyMem_DebugCheckAddress(api->api_id, q); + + if (r == NULL) { + return NULL; + } + if (nbytes > original_nbytes) { /* growing: mark new extra memory clean */ memset(q + original_nbytes, CLEANBYTE,