From a5d78cc208c24be62b50b6d1540e03be6612d3f2 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Sat, 2 Mar 2002 08:43:19 +0000 Subject: [PATCH] Whether platform malloc(0) returns NULL has nothing to do with whether platform realloc(p, 0) returns NULL, so MALLOC_ZERO_RETURNS_NULL can be correctly undefined yet realloc(p, 0) can return NULL anyway. Prevent realloc(p, 0) doing free(p) and returning NULL via a different hack. Would probably be better to get rid of MALLOC_ZERO_RETURNS_NULL entirely. Bugfix candidate. --- Include/pymem.h | 19 ++++++++++++------- Include/pyport.h | 12 ++++++++++-- Objects/object.c | 7 ++----- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Include/pymem.h b/Include/pymem.h index 86a69e45718..d09f38c72f6 100644 --- a/Include/pymem.h +++ b/Include/pymem.h @@ -111,13 +111,18 @@ extern DL_IMPORT(void) PyMem_Free(void *); /* Macros */ #define PyMem_NEW(type, n) \ ( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) ) -#define PyMem_RESIZE(p, type, n) \ - if ((p) == NULL) \ - (p) = (type *)(PyMem_MALLOC( \ - _PyMem_EXTRA + (n) * sizeof(type))); \ - else \ - (p) = (type *)(PyMem_REALLOC((p), \ - _PyMem_EXTRA + (n) * sizeof(type))) + +/* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */ +#define PyMem_RESIZE(p, type, n) \ + do { \ + size_t _sum = (n) * sizeof(type); \ + if (!_sum) \ + _sum = 1; \ + (p) = (type *)((p) ? \ + PyMem_REALLOC(p, _sum) : \ + PyMem_MALLOC(_sum)); \ + } while (0) + #define PyMem_DEL(p) PyMem_FREE(p) /* PyMem_XDEL is deprecated. To avoid the call when p is NULL, diff --git a/Include/pyport.h b/Include/pyport.h index 271ec431a36..a831b264f9f 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -366,8 +366,16 @@ extern double hypot(double, double); #endif #ifdef MALLOC_ZERO_RETURNS_NULL -/* XXX Always allocate one extra byte, since some malloc's return NULL - XXX for malloc(0) or realloc(p, 0). */ +/* Allocate an extra byte if the platform malloc(0) returns NULL. + Caution: this bears no relation to whether realloc(p, 0) returns NULL + when p != NULL. Even on platforms where malloc(0) does not return NULL, + realloc(p, 0) may act like free(p) and return NULL. Examples include + Windows, and Python's own obmalloc.c (as of 2-Mar-2002). For whatever + reason, our docs promise that PyMem_Realloc(p, 0) won't act like + free(p) or return NULL, so realloc() calls may have to be hacked + too, but MALLOC_ZERO_RETURNS_NULL's state is irrelevant to realloc (it + needs a different hack). +*/ #define _PyMem_EXTRA 1 #else #define _PyMem_EXTRA 0 diff --git a/Objects/object.c b/Objects/object.c index 8babf79a905..bcc129cd5c8 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1894,11 +1894,8 @@ PyMem_Malloc(size_t nbytes) void * PyMem_Realloc(void *p, size_t nbytes) { -#if _PyMem_EXTRA > 0 - if (nbytes == 0) - nbytes = _PyMem_EXTRA; -#endif - return PyMem_REALLOC(p, nbytes); + /* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */ + return PyMem_REALLOC(p, nbytes ? nbytes : 1); } void