From: Bruno Haible <bruno@clisp.org>
Date: Sat, 11 Nov 2023 19:04:02 +0000 (+0100)
Subject: malloca: Take advantage of CHERI bounds-checking.
X-Git-Tag: v1.0~598
X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=5c8fc31ab5db3372739a7ae9bf579cef946408ad;p=gnulib.git

malloca: Take advantage of CHERI bounds-checking.

* lib/malloca.h: Include <cheri.h>.
(malloca) [CHERI]: In the stack-allocation case, return a pointer with
a tight lower bound and a tight upper bound.
* lib/malloca.c: Include <cheri.h>.
(small_t) [CHERI]: Define as uintptr_t.
(mmalloca) [CHERI]: Return a pointer with a tight upper bound.
(freea) [CHERI]: Update.
---

diff --git a/ChangeLog b/ChangeLog
index 1fd39a4a44..af8ead5fc2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2023-11-11  Bruno Haible  <bruno@clisp.org>
+
+	malloca: Take advantage of CHERI bounds-checking.
+	* lib/malloca.h: Include <cheri.h>.
+	(malloca) [CHERI]: In the stack-allocation case, return a pointer with
+	a tight lower bound and a tight upper bound.
+	* lib/malloca.c: Include <cheri.h>.
+	(small_t) [CHERI]: Define as uintptr_t.
+	(mmalloca) [CHERI]: Return a pointer with a tight upper bound.
+	(freea) [CHERI]: Update.
+
 2023-11-11  Bruno Haible  <bruno@clisp.org>
 
 	safe-alloc: Take advantage of CHERI bounds-checking.
diff --git a/lib/malloca.c b/lib/malloca.c
index 690ce2324b..f98fdf152d 100644
--- a/lib/malloca.c
+++ b/lib/malloca.c
@@ -22,6 +22,9 @@
 #include "malloca.h"
 
 #include <stdckdint.h>
+#if defined __CHERI__
+# include <cheri.h>
+#endif
 
 #include "idx.h"
 
@@ -36,10 +39,15 @@
        allocation.
      - NULL comes from a failed heap allocation.  */
 
+#if defined __CHERI__
+/* 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 - 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__
+          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;
         }
@@ -101,7 +117,11 @@ freea (void *p)
     {
       char *cp = p;
       small_t *sp = p;
+# if defined __CHERI__
+      void *mem = sp[-1];
+# else
       void *mem = cp - sp[-1];
+# endif
       free (mem);
     }
 }
diff --git a/lib/malloca.h b/lib/malloca.h
index f68ddfe010..120f406880 100644
--- a/lib/malloca.h
+++ b/lib/malloca.h
@@ -28,6 +28,9 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <stdint.h>
+#if defined __CHERI__
+# include <cheri.h>
+#endif
 
 #include "xalloc-oversized.h"
 
@@ -68,12 +71,24 @@ extern void freea (void *p);
    memory allocated on the stack, that must be freed using freea() before
    the function returns.  Upon failure, it returns NULL.  */
 #if HAVE_ALLOCA
-# define malloca(N) \
-  ((N) < 4032 - (2 * sa_alignment_max - 1)                                   \
-   ? (void *) (((uintptr_t) (char *) alloca ((N) + 2 * sa_alignment_max - 1) \
-                + (2 * sa_alignment_max - 1))                                \
-               & ~(uintptr_t)(2 * sa_alignment_max - 1))                     \
-   : mmalloca (N))
+# if defined __CHERI__
+#  define malloca(N) \
+    ((N) < 4032 - (2 * sa_alignment_max - 1)                                  \
+     ? cheri_bounds_set ((void *) (((uintptr_t)                               \
+                                     (char *)                                 \
+                                      alloca ((N) + 2 * sa_alignment_max - 1) \
+                                    + (2 * sa_alignment_max - 1))             \
+                                   & ~(uintptr_t)(2 * sa_alignment_max - 1)), \
+                         (N))                                                 \
+     : mmalloca (N))
+# else
+#  define malloca(N) \
+    ((N) < 4032 - (2 * sa_alignment_max - 1)                                   \
+     ? (void *) (((uintptr_t) (char *) alloca ((N) + 2 * sa_alignment_max - 1) \
+                  + (2 * sa_alignment_max - 1))                                \
+                 & ~(uintptr_t)(2 * sa_alignment_max - 1))                     \
+     : mmalloca (N))
+# endif
 #else
 # define malloca(N) \
   mmalloca (N)