summaryrefslogtreecommitdiffstats
path: root/gl/malloca.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/malloca.c')
-rw-r--r--gl/malloca.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/gl/malloca.c b/gl/malloca.c
index f055b1e..e75c72d 100644
--- a/gl/malloca.c
+++ b/gl/malloca.c
@@ -1,5 +1,5 @@
1/* Safe automatic memory allocation. 1/* Safe automatic memory allocation.
2 Copyright (C) 2003, 2006-2007, 2009-2023 Free Software Foundation, Inc. 2 Copyright (C) 2003, 2006-2007, 2009-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003, 2018. 3 Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
4 4
5 This file is free software: you can redistribute it and/or modify 5 This file is free software: you can redistribute it and/or modify
@@ -22,6 +22,9 @@
22#include "malloca.h" 22#include "malloca.h"
23 23
24#include <stdckdint.h> 24#include <stdckdint.h>
25#if defined __CHERI_PURE_CAPABILITY__
26# include <cheri.h>
27#endif
25 28
26#include "idx.h" 29#include "idx.h"
27 30
@@ -36,10 +39,15 @@
36 allocation. 39 allocation.
37 - NULL comes from a failed heap allocation. */ 40 - NULL comes from a failed heap allocation. */
38 41
42#if defined __CHERI_PURE_CAPABILITY__
43/* Type for holding the original malloc() result. */
44typedef uintptr_t small_t;
45#else
39/* Type for holding very small pointer differences. */ 46/* Type for holding very small pointer differences. */
40typedef unsigned char small_t; 47typedef unsigned char small_t;
41/* Verify that it is wide enough. */ 48/* Verify that it is wide enough. */
42static_assert (2 * sa_alignment_max - 1 <= (small_t) -1); 49static_assert (2 * sa_alignment_max - 1 <= (small_t) -1);
50#endif
43 51
44void * 52void *
45mmalloca (size_t n) 53mmalloca (size_t n)
@@ -56,20 +64,28 @@ mmalloca (size_t n)
56 64
57 if (mem != NULL) 65 if (mem != NULL)
58 { 66 {
59 uintptr_t umem = (uintptr_t)mem, umemplus; 67 uintptr_t umem = (uintptr_t) mem;
60 /* The ckd_add avoids signed integer overflow on 68 /* The ckd_add avoids signed integer overflow on
61 theoretical platforms where UINTPTR_MAX <= INT_MAX. */ 69 theoretical platforms where UINTPTR_MAX <= INT_MAX. */
70 uintptr_t umemplus;
62 ckd_add (&umemplus, umem, sizeof (small_t) + sa_alignment_max - 1); 71 ckd_add (&umemplus, umem, sizeof (small_t) + sa_alignment_max - 1);
63 idx_t offset = ((umemplus & ~alignment2_mask) 72 idx_t offset = (umemplus - umemplus % (2 * sa_alignment_max)
64 + sa_alignment_max - umem); 73 + sa_alignment_max - umem);
65 void *vp = mem + offset; 74 void *p = mem + offset;
66 small_t *p = vp;
67 /* Here p >= mem + sizeof (small_t), 75 /* Here p >= mem + sizeof (small_t),
68 and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1 76 and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1
69 hence p + n <= mem + nplus. 77 hence p + n <= mem + nplus.
70 So, the memory range [p, p+n) lies in the allocated memory range 78 So, the memory range [p, p+n) lies in the allocated memory range
71 [mem, mem + nplus). */ 79 [mem, mem + nplus). */
72 p[-1] = offset; 80 small_t *sp = p;
81# if defined __CHERI_PURE_CAPABILITY__
82 sp[-1] = umem;
83 p = (char *) cheri_bounds_set ((char *) p - sizeof (small_t),
84 sizeof (small_t) + n)
85 + sizeof (small_t);
86# else
87 sp[-1] = offset;
88# endif
73 /* p ≡ sa_alignment_max mod 2*sa_alignment_max. */ 89 /* p ≡ sa_alignment_max mod 2*sa_alignment_max. */
74 return p; 90 return p;
75 } 91 }
@@ -90,15 +106,22 @@ void
90freea (void *p) 106freea (void *p)
91{ 107{
92 /* Check argument. */ 108 /* Check argument. */
93 if ((uintptr_t) p & (sa_alignment_max - 1)) 109 uintptr_t u = (uintptr_t) p;
110 if (u & (sa_alignment_max - 1))
94 { 111 {
95 /* p was not the result of a malloca() call. Invalid argument. */ 112 /* p was not the result of a malloca() call. Invalid argument. */
96 abort (); 113 abort ();
97 } 114 }
98 /* Determine whether p was a non-NULL pointer returned by mmalloca(). */ 115 /* Determine whether p was a non-NULL pointer returned by mmalloca(). */
99 if ((uintptr_t) p & sa_alignment_max) 116 if (u & sa_alignment_max)
100 { 117 {
101 void *mem = (char *) p - ((small_t *) p)[-1]; 118 char *cp = p;
119 small_t *sp = p;
120# if defined __CHERI_PURE_CAPABILITY__
121 void *mem = sp[-1];
122# else
123 void *mem = cp - sp[-1];
124# endif
102 free (mem); 125 free (mem);
103 } 126 }
104} 127}