bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] reallocarray: don’t crash if item size is 0


From: Paul Eggert
Subject: [PATCH] reallocarray: don’t crash if item size is 0
Date: Sun, 25 Apr 2021 18:26:08 -0700

This problem affects only platforms where xalloc_oversized
divides a number by the size arg.  Fix this by defining
xalloc_oversized (n, s) to work even if s == 0.
* lib/malloca.h, lib/xalloc-oversized.h: Document new behavior.
* lib/xalloc-oversized.h (__xalloc_oversized): Do not crash if S==0.
* tests/test-reallocarray.c (main): Test for the bug.
---
 ChangeLog                 | 10 ++++++++++
 lib/malloca.h             |  2 +-
 lib/xalloc-oversized.h    |  8 +++++---
 tests/test-reallocarray.c |  9 +++++++--
 4 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3a21db4f4..03b01b3d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2021-04-25  Paul Eggert  <eggert@cs.ucla.edu>
+
+       reallocarray: don’t crash if item size is 0
+       This problem affects only platforms where xalloc_oversized
+       divides a number by the size arg.  Fix this by defining
+       xalloc_oversized (n, s) to work even if s == 0.
+       * lib/malloca.h, lib/xalloc-oversized.h: Document new behavior.
+       * lib/xalloc-oversized.h (__xalloc_oversized): Do not crash if S==0.
+       * tests/test-reallocarray.c (main): Test for the bug.
+
 2021-04-24  Paul Eggert  <eggert@cs.ucla.edu>
 
        xmalloca, etc.: avoid unlikely trap
diff --git a/lib/malloca.h b/lib/malloca.h
index a255e3f04..d646d4102 100644
--- a/lib/malloca.h
+++ b/lib/malloca.h
@@ -76,7 +76,7 @@ extern void freea (void *p);
 
 /* nmalloca(N,S) is an overflow-safe variant of malloca (N * S).
    It allocates an array of N objects, each with S bytes of memory,
-   on the stack.  S must be positive and N must be nonnegative.
+   on the stack.  N and S should be nonnegative and free of side effects.
    The array must be freed using freea() before the function returns.  */
 #define nmalloca(n, s) \
   (xalloc_oversized (n, s) ? NULL : malloca ((n) * (size_t) (s)))
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 2619a2aab..dbaee4a29 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -22,19 +22,21 @@
 #include <stdint.h>
 
 /* True if N * S does not fit into both ptrdiff_t and size_t.
-   S must be positive and N must be nonnegative.
+   N and S should be nonnegative and free of side effects.
    This expands to a constant expression if N and S are both constants.
    By gnulib convention, SIZE_MAX represents overflow in size_t
    calculations, so the conservative size_t-based dividend to use here
    is SIZE_MAX - 1.  */
 #define __xalloc_oversized(n, s) \
-  ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n))
+  ((s) != 0 \
+   && ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) \
+       < (n)))
 
 /* Return 1 if and only if an array of N objects, each of size S,
    cannot exist reliably because its total size in bytes would exceed
    MIN (PTRDIFF_MAX, SIZE_MAX - 1).
 
-   N must be nonnegative and S must be positive.
+   N and S should be nonnegative and free of side effects.
 
    Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can
    misbehave if N and S are both narrower than ptrdiff_t and size_t,
diff --git a/tests/test-reallocarray.c b/tests/test-reallocarray.c
index 973f22ba6..6de355e6b 100644
--- a/tests/test-reallocarray.c
+++ b/tests/test-reallocarray.c
@@ -26,12 +26,12 @@ SIGNATURE_CHECK (reallocarray, void *, (void *, size_t, 
size_t));
 int
 main ()
 {
-  void *volatile p = NULL;
-
   /* Check that reallocarray fails when requested to allocate a block
      of memory larger than PTRDIFF_MAX or SIZE_MAX bytes.  */
   for (size_t n = 2; n != 0; n <<= 1)
     {
+      void *volatile p = NULL;
+
       p = reallocarray (p, PTRDIFF_MAX / n + 1, n);
       if (p)
         return 1;
@@ -43,6 +43,11 @@ main ()
         return 3;
       if (errno != ENOMEM)
         return 4;
+
+      /* Reallocarray should not crash with zero sizes.  */
+      p = reallocarray (p, 0, n);
+      p = reallocarray (p, n, 0);
+      free (p);
     }
 
   return 0;
-- 
2.27.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]