Unverified Kaydet (Commit) 9ed83c40 authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

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.
üst ec2cbdd1
...@@ -3273,34 +3273,39 @@ typedef struct { ...@@ -3273,34 +3273,39 @@ typedef struct {
void *realloc_ptr; void *realloc_ptr;
size_t realloc_new_size; size_t realloc_new_size;
void *free_ptr; void *free_ptr;
void *ctx;
} alloc_hook_t; } alloc_hook_t;
static void* hook_malloc (void* ctx, size_t size) static void* hook_malloc(void* ctx, size_t size)
{ {
alloc_hook_t *hook = (alloc_hook_t *)ctx; alloc_hook_t *hook = (alloc_hook_t *)ctx;
hook->ctx = ctx;
hook->malloc_size = size; hook->malloc_size = size;
return hook->alloc.malloc(hook->alloc.ctx, size); return hook->alloc.malloc(hook->alloc.ctx, size);
} }
static void* hook_calloc (void* ctx, size_t nelem, size_t elsize) static void* hook_calloc(void* ctx, size_t nelem, size_t elsize)
{ {
alloc_hook_t *hook = (alloc_hook_t *)ctx; alloc_hook_t *hook = (alloc_hook_t *)ctx;
hook->ctx = ctx;
hook->calloc_nelem = nelem; hook->calloc_nelem = nelem;
hook->calloc_elsize = elsize; hook->calloc_elsize = elsize;
return hook->alloc.calloc(hook->alloc.ctx, nelem, elsize); return hook->alloc.calloc(hook->alloc.ctx, nelem, elsize);
} }
static void* hook_realloc (void* ctx, void* ptr, size_t new_size) static void* hook_realloc(void* ctx, void* ptr, size_t new_size)
{ {
alloc_hook_t *hook = (alloc_hook_t *)ctx; alloc_hook_t *hook = (alloc_hook_t *)ctx;
hook->ctx = ctx;
hook->realloc_ptr = ptr; hook->realloc_ptr = ptr;
hook->realloc_new_size = new_size; hook->realloc_new_size = new_size;
return hook->alloc.realloc(hook->alloc.ctx, ptr, new_size); return hook->alloc.realloc(hook->alloc.ctx, ptr, new_size);
} }
static void hook_free (void *ctx, void *ptr) static void hook_free(void *ctx, void *ptr)
{ {
alloc_hook_t *hook = (alloc_hook_t *)ctx; alloc_hook_t *hook = (alloc_hook_t *)ctx;
hook->ctx = ctx;
hook->free_ptr = ptr; hook->free_ptr = ptr;
hook->alloc.free(hook->alloc.ctx, ptr); hook->alloc.free(hook->alloc.ctx, ptr);
} }
...@@ -3325,7 +3330,9 @@ test_setallocators(PyMemAllocatorDomain domain) ...@@ -3325,7 +3330,9 @@ test_setallocators(PyMemAllocatorDomain domain)
PyMem_GetAllocator(domain, &hook.alloc); PyMem_GetAllocator(domain, &hook.alloc);
PyMem_SetAllocator(domain, &alloc); PyMem_SetAllocator(domain, &alloc);
/* malloc, realloc, free */
size = 42; size = 42;
hook.ctx = NULL;
switch(domain) switch(domain)
{ {
case PYMEM_DOMAIN_RAW: ptr = PyMem_RawMalloc(size); break; case PYMEM_DOMAIN_RAW: ptr = PyMem_RawMalloc(size); break;
...@@ -3334,11 +3341,18 @@ test_setallocators(PyMemAllocatorDomain domain) ...@@ -3334,11 +3341,18 @@ test_setallocators(PyMemAllocatorDomain domain)
default: ptr = NULL; break; default: ptr = NULL; break;
} }
#define CHECK_CTX(FUNC) \
if (hook.ctx != &hook) { \
error_msg = FUNC " wrong context"; \
goto fail; \
} \
hook.ctx = NULL; /* reset for next check */
if (ptr == NULL) { if (ptr == NULL) {
error_msg = "malloc failed"; error_msg = "malloc failed";
goto fail; goto fail;
} }
CHECK_CTX("malloc");
if (hook.malloc_size != size) { if (hook.malloc_size != size) {
error_msg = "malloc invalid size"; error_msg = "malloc invalid size";
goto fail; goto fail;
...@@ -3357,7 +3371,7 @@ test_setallocators(PyMemAllocatorDomain domain) ...@@ -3357,7 +3371,7 @@ test_setallocators(PyMemAllocatorDomain domain)
error_msg = "realloc failed"; error_msg = "realloc failed";
goto fail; goto fail;
} }
CHECK_CTX("realloc");
if (hook.realloc_ptr != ptr if (hook.realloc_ptr != ptr
|| hook.realloc_new_size != size2) { || hook.realloc_new_size != size2) {
error_msg = "realloc invalid parameters"; error_msg = "realloc invalid parameters";
...@@ -3371,11 +3385,13 @@ test_setallocators(PyMemAllocatorDomain domain) ...@@ -3371,11 +3385,13 @@ test_setallocators(PyMemAllocatorDomain domain)
case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr2); break; case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr2); break;
} }
CHECK_CTX("free");
if (hook.free_ptr != ptr2) { if (hook.free_ptr != ptr2) {
error_msg = "free invalid pointer"; error_msg = "free invalid pointer";
goto fail; goto fail;
} }
/* calloc, free */
nelem = 2; nelem = 2;
elsize = 5; elsize = 5;
switch(domain) switch(domain)
...@@ -3390,12 +3406,13 @@ test_setallocators(PyMemAllocatorDomain domain) ...@@ -3390,12 +3406,13 @@ test_setallocators(PyMemAllocatorDomain domain)
error_msg = "calloc failed"; error_msg = "calloc failed";
goto fail; goto fail;
} }
CHECK_CTX("calloc");
if (hook.calloc_nelem != nelem || hook.calloc_elsize != elsize) { if (hook.calloc_nelem != nelem || hook.calloc_elsize != elsize) {
error_msg = "calloc invalid nelem or elsize"; error_msg = "calloc invalid nelem or elsize";
goto fail; goto fail;
} }
hook.free_ptr = NULL;
switch(domain) switch(domain)
{ {
case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break; case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break;
...@@ -3403,6 +3420,12 @@ test_setallocators(PyMemAllocatorDomain domain) ...@@ -3403,6 +3420,12 @@ test_setallocators(PyMemAllocatorDomain domain)
case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break; case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break;
} }
CHECK_CTX("calloc free");
if (hook.free_ptr != ptr) {
error_msg = "calloc free invalid pointer";
goto fail;
}
Py_INCREF(Py_None); Py_INCREF(Py_None);
res = Py_None; res = Py_None;
goto finally; goto finally;
...@@ -3413,6 +3436,8 @@ fail: ...@@ -3413,6 +3436,8 @@ fail:
finally: finally:
PyMem_SetAllocator(domain, &hook.alloc); PyMem_SetAllocator(domain, &hook.alloc);
return res; return res;
#undef CHECK_CTX
} }
static PyObject * static PyObject *
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment