]> Savannah Git Hosting - gnulib.git/commitdiff
malloca: improve -fanalyzer malloc checking
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 2 Aug 2021 00:35:17 +0000 (17:35 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 2 Aug 2021 01:06:54 +0000 (18:06 -0700)
ChangeLog
lib/malloca.c
lib/malloca.h

index 6bad8ceb6710f9ea63626ee9886e9771c3bb92d9..166618a42cd14a08e3087288fbc3c6673d000e80 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,11 +3,14 @@
        maint: improve -fanalyzer malloc checking
        * lib/backup-internal.h, lib/backupfile.h:
        * lib/canonicalize.h, lib/dfa.h, lib/dirname.h, lib/exclude.h:
-       * lib/filenamecat.h:
+       * lib/filenamecat.h, lib/malloca.h:
        Add malloc-related attributes and include stdlib.h as needed.
        * lib/dfa.c: Include verify.h.
        (assume_nonnull): New macro.
        (dfamust): Use it to pacify GCC.
+       * lib/malloca.c (mmalloca): Redo to pacify GCC, to cut down on the
+       number of casts, and to avoid signed integer overflow on
+       theoretical platforms.
 
 2021-08-01  Jim Meyering  <meyering@fb.com>
 
index d7ad095b5abf23b1610a37fe04344f7b4c01c4fd..b4884234a28a4e60cbb8a55095666af84d6d66aa 100644 (file)
@@ -47,7 +47,8 @@ mmalloca (size_t n)
 #if HAVE_ALLOCA
   /* Allocate one more word, used to determine the address to pass to freea(),
      and room for the alignment ≡ sa_alignment_max mod 2*sa_alignment_max.  */
-  int plus = sizeof (small_t) + 2 * sa_alignment_max - 1;
+  uintptr_t alignment2_mask = 2 * sa_alignment_max - 1;
+  int plus = sizeof (small_t) + alignment2_mask;
   idx_t nplus;
   if (!INT_ADD_WRAPV (n, plus, &nplus) && !xalloc_oversized (nplus, 1))
     {
@@ -55,16 +56,21 @@ mmalloca (size_t n)
 
       if (mem != NULL)
         {
-          char *p =
-            (char *)((((uintptr_t)mem + sizeof (small_t) + sa_alignment_max - 1)
-                      & ~(uintptr_t)(2 * sa_alignment_max - 1))
-                     + sa_alignment_max);
+          uintptr_t umem = (uintptr_t)mem, umemplus;
+          /* The INT_ADD_WRAPV avoids signed integer overflow on
+             theoretical platforms where UINTPTR_MAX <= INT_MAX.  */
+          INT_ADD_WRAPV (umem, sizeof (small_t) + sa_alignment_max - 1,
+                         &umemplus);
+          idx_t offset = ((umemplus & ~alignment2_mask)
+                          + sa_alignment_max - umem);
+          void *vp = mem + offset;
+          small_t *p = vp;
           /* Here p >= mem + sizeof (small_t),
              and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1
              hence p + n <= mem + nplus.
              So, the memory range [p, p+n) lies in the allocated memory range
              [mem, mem + nplus).  */
-          ((small_t *) p)[-1] = p - mem;
+          p[-1] = offset;
           /* p ≡ sa_alignment_max mod 2*sa_alignment_max.  */
           return p;
         }
index 6fa1d8b2057aeadec0ae7bb111398877912f3882..dbbec3f065247c0ea4d877996eb654f62b24eb3a 100644 (file)
@@ -65,7 +65,6 @@ extern "C" {
 # define malloca(N) \
   mmalloca (N)
 #endif
-extern void * mmalloca (size_t n);
 
 /* Free a block of memory allocated through malloca().  */
 #if HAVE_ALLOCA
@@ -74,6 +73,10 @@ extern void freea (void *p);
 # define freea free
 #endif
 
+extern void *mmalloca (size_t n)
+  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (freea, 1)
+  _GL_ATTRIBUTE_ALLOC_SIZE ((1));
+
 /* 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.  N and S should be nonnegative and free of side effects.