diff options
Diffstat (limited to 'lib/malloca.c')
-rw-r--r-- | lib/malloca.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/lib/malloca.c b/lib/malloca.c index 1e19978d..e75c72df 100644 --- a/lib/malloca.c +++ b/lib/malloca.c @@ -1,5 +1,5 @@ /* Safe automatic memory allocation. - Copyright (C) 2003, 2006-2007, 2009-2022 Free Software Foundation, Inc. + Copyright (C) 2003, 2006-2007, 2009-2024 Free Software Foundation, Inc. Written by Bruno Haible <bruno@clisp.org>, 2003, 2018. This file is free software: you can redistribute it and/or modify @@ -22,6 +22,9 @@ #include "malloca.h" #include <stdckdint.h> +#if defined __CHERI_PURE_CAPABILITY__ +# include <cheri.h> +#endif #include "idx.h" @@ -36,10 +39,15 @@ allocation. - NULL comes from a failed heap allocation. */ +#if defined __CHERI_PURE_CAPABILITY__ +/* Type for holding the original malloc() result. */ +typedef uintptr_t small_t; +#else /* Type for holding very small pointer differences. */ typedef unsigned char small_t; /* Verify that it is wide enough. */ static_assert (2 * sa_alignment_max - 1 <= (small_t) -1); +#endif void * mmalloca (size_t n) @@ -56,20 +64,28 @@ mmalloca (size_t n) if (mem != NULL) { - uintptr_t umem = (uintptr_t)mem, umemplus; + uintptr_t umem = (uintptr_t) mem; /* The ckd_add avoids signed integer overflow on theoretical platforms where UINTPTR_MAX <= INT_MAX. */ + uintptr_t umemplus; ckd_add (&umemplus, umem, sizeof (small_t) + sa_alignment_max - 1); - idx_t offset = ((umemplus & ~alignment2_mask) + idx_t offset = (umemplus - umemplus % (2 * sa_alignment_max) + sa_alignment_max - umem); - void *vp = mem + offset; - small_t *p = vp; + void *p = mem + offset; /* 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). */ - p[-1] = offset; + small_t *sp = p; +# if defined __CHERI_PURE_CAPABILITY__ + sp[-1] = umem; + p = (char *) cheri_bounds_set ((char *) p - sizeof (small_t), + sizeof (small_t) + n) + + sizeof (small_t); +# else + sp[-1] = offset; +# endif /* p ≡ sa_alignment_max mod 2*sa_alignment_max. */ return p; } @@ -90,15 +106,22 @@ void freea (void *p) { /* Check argument. */ - if ((uintptr_t) p & (sa_alignment_max - 1)) + uintptr_t u = (uintptr_t) p; + if (u & (sa_alignment_max - 1)) { /* p was not the result of a malloca() call. Invalid argument. */ abort (); } /* Determine whether p was a non-NULL pointer returned by mmalloca(). */ - if ((uintptr_t) p & sa_alignment_max) + if (u & sa_alignment_max) { - void *mem = (char *) p - ((small_t *) p)[-1]; + char *cp = p; + small_t *sp = p; +# if defined __CHERI_PURE_CAPABILITY__ + void *mem = sp[-1]; +# else + void *mem = cp - sp[-1]; +# endif free (mem); } } |