about summary refs log tree commit diff
path: root/lib/util/mallocvar.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util/mallocvar.h')
-rw-r--r--lib/util/mallocvar.h60
1 files changed, 41 insertions, 19 deletions
diff --git a/lib/util/mallocvar.h b/lib/util/mallocvar.h
index 00ba6484..23b28c40 100644
--- a/lib/util/mallocvar.h
+++ b/lib/util/mallocvar.h
@@ -24,30 +24,40 @@ extern "C" {
 
 static __inline__ void
 mallocProduct(void **      const resultP,
-              unsigned int const factor1,
+              size_t       const factor1,
               unsigned int const factor2) {
 /*----------------------------------------------------------------------------
    malloc a space whose size in bytes is the product of 'factor1' and
-   'factor2'.  But if that size cannot be represented as an unsigned int,
-   return NULL without allocating anything.  Also return NULL if the malloc
-   fails.
+   'factor2'.  But if the malloc fails, or that size is too large even to
+   request from malloc, return NULL without allocating anything.
 
    If either factor is zero, malloc a single byte.
-
-   Note that malloc() actually takes a size_t size argument, so the
-   proper test would be whether the size can be represented by size_t,
-   not unsigned int.  But there is no reliable indication available to
-   us, like UINT_MAX, of what the limitations of size_t are.  We
-   assume size_t is at least as expressive as unsigned int and that
-   nobody really needs to allocate more than 4GB of memory.
 -----------------------------------------------------------------------------*/
+    /* C99 introduces SIZE_MAX, the maximum size_t value.
+
+       Pre-C99, we do the best we can, assuming conventional encoding of
+       numbers and that size_t is unsigned.
+    */
+    size_t const sizeMax =
+#if defined(SIZE_MAX)
+        SIZE_MAX
+#else
+        ~((size_t)0)
+#endif
+        ;
+
     if (factor1 == 0 || factor2 == 0)
         *resultP = malloc(1);
     else {
-        if (UINT_MAX / factor2 < factor1)
+        /* N.B. The type of malloc's argument is size_t */
+        if ((size_t)factor2 != factor2)
             *resultP = NULL;
-        else
-            *resultP = malloc(factor1 * factor2);
+        else {
+            if (sizeMax / factor2 < factor1)
+                *resultP = NULL;
+            else
+                *resultP = malloc(factor1 * factor2);
+        }
     }
 }
 
@@ -55,18 +65,30 @@ mallocProduct(void **      const resultP,
 
 static __inline__ void
 reallocProduct(void **      const blockP,
-               unsigned int const factor1,
+               size_t       const factor1,
                unsigned int const factor2) {
 
+    size_t const sizeMax =
+#if defined(SIZE_MAX)
+        SIZE_MAX
+#else
+        ~((size_t)0)
+#endif
+        ;
+
     void * const oldBlockP = *blockP;
 
     void * newBlockP;
 
-    if (UINT_MAX / factor2 < factor1)
+    /* N.B. The type of realloc's argument is size_t */
+    if ((size_t)factor2 != factor2)
         newBlockP = NULL;
-    else
-        newBlockP = realloc(oldBlockP, factor1 * factor2);
-
+    else {
+        if (sizeMax / factor2 < factor1)
+            newBlockP = NULL;
+        else
+            newBlockP = realloc(oldBlockP, factor1 * factor2);
+    }
     if (newBlockP)
         *blockP = newBlockP;
     else {