diff options
Diffstat (limited to 'gl/malloca.c')
-rw-r--r-- | gl/malloca.c | 41 |
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. */ | ||
44 | typedef uintptr_t small_t; | ||
45 | #else | ||
39 | /* Type for holding very small pointer differences. */ | 46 | /* Type for holding very small pointer differences. */ |
40 | typedef unsigned char small_t; | 47 | typedef unsigned char small_t; |
41 | /* Verify that it is wide enough. */ | 48 | /* Verify that it is wide enough. */ |
42 | static_assert (2 * sa_alignment_max - 1 <= (small_t) -1); | 49 | static_assert (2 * sa_alignment_max - 1 <= (small_t) -1); |
50 | #endif | ||
43 | 51 | ||
44 | void * | 52 | void * |
45 | mmalloca (size_t n) | 53 | mmalloca (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 | |||
90 | freea (void *p) | 106 | freea (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 | } |