summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2021-08-01 17:35:17 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2021-08-01 18:06:54 -0700
commit8c6a99453e4a38fe6b602718e7b5e68444870e07 (patch)
treed235169d6871faf9d8647a57c5e6cd701d33f9bd /lib
parentb279b399553d273317a7faa59c3ebbfba0c353cd (diff)
downloadgnulib-8c6a99453e4a38fe6b602718e7b5e68444870e07.tar.gz
malloca: improve -fanalyzer malloc checking
Diffstat (limited to 'lib')
-rw-r--r--lib/malloca.c18
-rw-r--r--lib/malloca.h5
2 files changed, 16 insertions, 7 deletions
diff --git a/lib/malloca.c b/lib/malloca.c
index d7ad095b5a..b4884234a2 100644
--- a/lib/malloca.c
+++ b/lib/malloca.c
@@ -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;
}
diff --git a/lib/malloca.h b/lib/malloca.h
index 6fa1d8b205..dbbec3f065 100644
--- a/lib/malloca.h
+++ b/lib/malloca.h
@@ -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.