Skip to content

Commit 9ed83c4

Browse files
authored
bpo-18835: Cleanup pymalloc (#4200)
Cleanup pymalloc: * Rename _PyObject_Alloc() to pymalloc_alloc() * Rename _PyObject_FreeImpl() to pymalloc_free() * Rename _PyObject_Realloc() to pymalloc_realloc() * pymalloc_alloc() and pymalloc_realloc() don't fallback on the raw allocator anymore, it now must be done by the caller * Add "success" and "failed" labels to pymalloc_alloc() and pymalloc_free() * pymalloc_alloc() and pymalloc_free() don't update num_allocated_blocks anymore: it should be done in the caller * _PyObject_Calloc() is now responsible to fill the memory block allocated by pymalloc with zeros * Simplify pymalloc_alloc() prototype * _PyObject_Realloc() now calls _PyObject_Malloc() rather than calling directly pymalloc_alloc() _PyMem_DebugRawAlloc() and _PyMem_DebugRawRealloc(): * document the layout of a memory block * don't increase the serial number if the allocation failed * check for integer overflow before computing the total size * add a 'data' variable to make the code easiler to follow test_setallocators() of _testcapimodule.c now test also the context.
1 parent ec2cbdd commit 9ed83c4

File tree

2 files changed

+565
-479
lines changed

2 files changed

+565
-479
lines changed

Modules/_testcapimodule.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,34 +3273,39 @@ typedef struct {
32733273
void *realloc_ptr;
32743274
size_t realloc_new_size;
32753275
void *free_ptr;
3276+
void *ctx;
32763277
} alloc_hook_t;
32773278

3278-
static void* hook_malloc (void* ctx, size_t size)
3279+
static void* hook_malloc(void* ctx, size_t size)
32793280
{
32803281
alloc_hook_t *hook = (alloc_hook_t *)ctx;
3282+
hook->ctx = ctx;
32813283
hook->malloc_size = size;
32823284
return hook->alloc.malloc(hook->alloc.ctx, size);
32833285
}
32843286

3285-
static void* hook_calloc (void* ctx, size_t nelem, size_t elsize)
3287+
static void* hook_calloc(void* ctx, size_t nelem, size_t elsize)
32863288
{
32873289
alloc_hook_t *hook = (alloc_hook_t *)ctx;
3290+
hook->ctx = ctx;
32883291
hook->calloc_nelem = nelem;
32893292
hook->calloc_elsize = elsize;
32903293
return hook->alloc.calloc(hook->alloc.ctx, nelem, elsize);
32913294
}
32923295

3293-
static void* hook_realloc (void* ctx, void* ptr, size_t new_size)
3296+
static void* hook_realloc(void* ctx, void* ptr, size_t new_size)
32943297
{
32953298
alloc_hook_t *hook = (alloc_hook_t *)ctx;
3299+
hook->ctx = ctx;
32963300
hook->realloc_ptr = ptr;
32973301
hook->realloc_new_size = new_size;
32983302
return hook->alloc.realloc(hook->alloc.ctx, ptr, new_size);
32993303
}
33003304

3301-
static void hook_free (void *ctx, void *ptr)
3305+
static void hook_free(void *ctx, void *ptr)
33023306
{
33033307
alloc_hook_t *hook = (alloc_hook_t *)ctx;
3308+
hook->ctx = ctx;
33043309
hook->free_ptr = ptr;
33053310
hook->alloc.free(hook->alloc.ctx, ptr);
33063311
}
@@ -3325,7 +3330,9 @@ test_setallocators(PyMemAllocatorDomain domain)
33253330
PyMem_GetAllocator(domain, &hook.alloc);
33263331
PyMem_SetAllocator(domain, &alloc);
33273332

3333+
/* malloc, realloc, free */
33283334
size = 42;
3335+
hook.ctx = NULL;
33293336
switch(domain)
33303337
{
33313338
case PYMEM_DOMAIN_RAW: ptr = PyMem_RawMalloc(size); break;
@@ -3334,11 +3341,18 @@ test_setallocators(PyMemAllocatorDomain domain)
33343341
default: ptr = NULL; break;
33353342
}
33363343

3344+
#define CHECK_CTX(FUNC) \
3345+
if (hook.ctx != &hook) { \
3346+
error_msg = FUNC " wrong context"; \
3347+
goto fail; \
3348+
} \
3349+
hook.ctx = NULL; /* reset for next check */
3350+
33373351
if (ptr == NULL) {
33383352
error_msg = "malloc failed";
33393353
goto fail;
33403354
}
3341-
3355+
CHECK_CTX("malloc");
33423356
if (hook.malloc_size != size) {
33433357
error_msg = "malloc invalid size";
33443358
goto fail;
@@ -3357,7 +3371,7 @@ test_setallocators(PyMemAllocatorDomain domain)
33573371
error_msg = "realloc failed";
33583372
goto fail;
33593373
}
3360-
3374+
CHECK_CTX("realloc");
33613375
if (hook.realloc_ptr != ptr
33623376
|| hook.realloc_new_size != size2) {
33633377
error_msg = "realloc invalid parameters";
@@ -3371,11 +3385,13 @@ test_setallocators(PyMemAllocatorDomain domain)
33713385
case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr2); break;
33723386
}
33733387

3388+
CHECK_CTX("free");
33743389
if (hook.free_ptr != ptr2) {
33753390
error_msg = "free invalid pointer";
33763391
goto fail;
33773392
}
33783393

3394+
/* calloc, free */
33793395
nelem = 2;
33803396
elsize = 5;
33813397
switch(domain)
@@ -3390,19 +3406,26 @@ test_setallocators(PyMemAllocatorDomain domain)
33903406
error_msg = "calloc failed";
33913407
goto fail;
33923408
}
3393-
3409+
CHECK_CTX("calloc");
33943410
if (hook.calloc_nelem != nelem || hook.calloc_elsize != elsize) {
33953411
error_msg = "calloc invalid nelem or elsize";
33963412
goto fail;
33973413
}
33983414

3415+
hook.free_ptr = NULL;
33993416
switch(domain)
34003417
{
34013418
case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break;
34023419
case PYMEM_DOMAIN_MEM: PyMem_Free(ptr); break;
34033420
case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break;
34043421
}
34053422

3423+
CHECK_CTX("calloc free");
3424+
if (hook.free_ptr != ptr) {
3425+
error_msg = "calloc free invalid pointer";
3426+
goto fail;
3427+
}
3428+
34063429
Py_INCREF(Py_None);
34073430
res = Py_None;
34083431
goto finally;
@@ -3413,6 +3436,8 @@ test_setallocators(PyMemAllocatorDomain domain)
34133436
finally:
34143437
PyMem_SetAllocator(domain, &hook.alloc);
34153438
return res;
3439+
3440+
#undef CHECK_CTX
34163441
}
34173442

34183443
static PyObject *

0 commit comments

Comments
 (0)