Whether platform malloc(0) returns NULL has nothing to do with whether
authorTim Peters <tim.peters@gmail.com>
Sat, 2 Mar 2002 08:43:19 +0000 (08:43 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 2 Mar 2002 08:43:19 +0000 (08:43 +0000)
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
Include/pyport.h
Objects/object.c

index 86a69e45718f9b9cadf859405683fb2e808ec6be..d09f38c72f60153f87ec78972fcf7481116302c3 100644 (file)
@@ -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,
index 271ec431a36a1bf388d0b87654c01095422b9eff..a831b264f9f40fbc32f09ba14b9bcb1a751fa8b3 100644 (file)
@@ -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
index 8babf79a9050c0556ec369492144aaff103b4d0c..bcc129cd5c89cf4799141343a3722c3a537e9fa9 100644 (file)
@@ -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