summaryrefslogtreecommitdiff
path: root/lib/malloca.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/malloca.c')
-rw-r--r--lib/malloca.c41
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);
}
}