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);      }  } | 
