aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-12-09 13:57:38 -0800
committerPaul Eggert2017-12-12 15:17:12 -0800
commit4295050e1194af13afa26403dd3ebdff80824ae0 (patch)
tree354002f3c84f4d8341bb07c5f68529f660a9a405 /src
parent881abfc7fb55db2d00adf352100cc58a6a86c176 (diff)
downloademacs-4295050e1194af13afa26403dd3ebdff80824ae0.tar.gz
emacs-4295050e1194af13afa26403dd3ebdff80824ae0.zip
Narrow pointer bounds when appropriate
This typically occurs in a storage manager, where the caller is expected to access only the newly-allocated object, instead of using the returned value to access unrelated parts of the heap. * src/alloc.c (allocate_string, allocate_string_data) (compact_small_strings, find_string_data_in_pure) (sweep_strings, setup_on_free_list, allocate_vectorlike (pure_alloc): * src/bytecode.c (exec_byte_code): * src/callint.c (Fcall_interactively): * src/dispnew.c (scrolling): * src/editfns.c (styled_format): * src/frame.c (xrdb_get_resource, x_get_resource_string): * src/fringe.c (Fdefine_fringe_bitmap): * src/gmalloc.c (malloc, realloc, aligned_alloc): Narrow pointer bounds when appropriate. * src/alloc.c (SDATA_OF_STRING): * src/lisp.h (make_lisp_symbol) [__CHKP__]: Widen bounds here, though. * src/bytecode.c, src/callint.c, src/dispnew.c, src/editfns.c: * src/emacs.c, src/frame.c, src/fringe.c: Include ptr-bounds.h. * src/ptr-bounds.h (ptr_bounds_clip): New function.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c31
-rw-r--r--src/bytecode.c15
-rw-r--r--src/callint.c4
-rw-r--r--src/dispnew.c6
-rw-r--r--src/editfns.c9
-rw-r--r--src/emacs.c1
-rw-r--r--src/frame.c5
-rw-r--r--src/fringe.c5
-rw-r--r--src/gmalloc.c10
-rw-r--r--src/lisp.h9
-rw-r--r--src/ptr-bounds.h27
11 files changed, 93 insertions, 29 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 96b9aaa0d2d..9197ff12ef5 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1727,7 +1727,8 @@ static EMACS_INT total_string_bytes;
1727 a pointer to the `u.data' member of its sdata structure; the 1727 a pointer to the `u.data' member of its sdata structure; the
1728 structure starts at a constant offset in front of that. */ 1728 structure starts at a constant offset in front of that. */
1729 1729
1730#define SDATA_OF_STRING(S) ((sdata *) ((S)->u.s.data - SDATA_DATA_OFFSET)) 1730#define SDATA_OF_STRING(S) ptr_bounds_init ((sdata *) ((S)->u.s.data \
1731 - SDATA_DATA_OFFSET))
1731 1732
1732 1733
1733#ifdef GC_CHECK_STRING_OVERRUN 1734#ifdef GC_CHECK_STRING_OVERRUN
@@ -1919,7 +1920,7 @@ allocate_string (void)
1919 /* Every string on a free list should have NULL data pointer. */ 1920 /* Every string on a free list should have NULL data pointer. */
1920 s->u.s.data = NULL; 1921 s->u.s.data = NULL;
1921 NEXT_FREE_LISP_STRING (s) = string_free_list; 1922 NEXT_FREE_LISP_STRING (s) = string_free_list;
1922 string_free_list = s; 1923 string_free_list = ptr_bounds_clip (s, sizeof *s);
1923 } 1924 }
1924 1925
1925 total_free_strings += STRING_BLOCK_SIZE; 1926 total_free_strings += STRING_BLOCK_SIZE;
@@ -2034,7 +2035,7 @@ allocate_string_data (struct Lisp_String *s,
2034 2035
2035 MALLOC_UNBLOCK_INPUT; 2036 MALLOC_UNBLOCK_INPUT;
2036 2037
2037 s->u.s.data = SDATA_DATA (data); 2038 s->u.s.data = ptr_bounds_clip (SDATA_DATA (data), nbytes + 1);
2038#ifdef GC_CHECK_STRING_BYTES 2039#ifdef GC_CHECK_STRING_BYTES
2039 SDATA_NBYTES (data) = nbytes; 2040 SDATA_NBYTES (data) = nbytes;
2040#endif 2041#endif
@@ -2120,7 +2121,7 @@ sweep_strings (void)
2120 2121
2121 /* Put the string on the free-list. */ 2122 /* Put the string on the free-list. */
2122 NEXT_FREE_LISP_STRING (s) = string_free_list; 2123 NEXT_FREE_LISP_STRING (s) = string_free_list;
2123 string_free_list = s; 2124 string_free_list = ptr_bounds_clip (s, sizeof *s);
2124 ++nfree; 2125 ++nfree;
2125 } 2126 }
2126 } 2127 }
@@ -2128,7 +2129,7 @@ sweep_strings (void)
2128 { 2129 {
2129 /* S was on the free-list before. Put it there again. */ 2130 /* S was on the free-list before. Put it there again. */
2130 NEXT_FREE_LISP_STRING (s) = string_free_list; 2131 NEXT_FREE_LISP_STRING (s) = string_free_list;
2131 string_free_list = s; 2132 string_free_list = ptr_bounds_clip (s, sizeof *s);
2132 ++nfree; 2133 ++nfree;
2133 } 2134 }
2134 } 2135 }
@@ -2224,9 +2225,9 @@ compact_small_strings (void)
2224 nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from); 2225 nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from);
2225 eassert (nbytes <= LARGE_STRING_BYTES); 2226 eassert (nbytes <= LARGE_STRING_BYTES);
2226 2227
2227 nbytes = SDATA_SIZE (nbytes); 2228 ptrdiff_t size = SDATA_SIZE (nbytes);
2228 sdata *from_end = (sdata *) ((char *) from 2229 sdata *from_end = (sdata *) ((char *) from
2229 + nbytes + GC_STRING_EXTRA); 2230 + size + GC_STRING_EXTRA);
2230 2231
2231#ifdef GC_CHECK_STRING_OVERRUN 2232#ifdef GC_CHECK_STRING_OVERRUN
2232 if (memcmp (string_overrun_cookie, 2233 if (memcmp (string_overrun_cookie,
@@ -2240,22 +2241,23 @@ compact_small_strings (void)
2240 { 2241 {
2241 /* If TB is full, proceed with the next sblock. */ 2242 /* If TB is full, proceed with the next sblock. */
2242 sdata *to_end = (sdata *) ((char *) to 2243 sdata *to_end = (sdata *) ((char *) to
2243 + nbytes + GC_STRING_EXTRA); 2244 + size + GC_STRING_EXTRA);
2244 if (to_end > tb_end) 2245 if (to_end > tb_end)
2245 { 2246 {
2246 tb->next_free = to; 2247 tb->next_free = to;
2247 tb = tb->next; 2248 tb = tb->next;
2248 tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); 2249 tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
2249 to = tb->data; 2250 to = tb->data;
2250 to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); 2251 to_end = (sdata *) ((char *) to + size + GC_STRING_EXTRA);
2251 } 2252 }
2252 2253
2253 /* Copy, and update the string's `data' pointer. */ 2254 /* Copy, and update the string's `data' pointer. */
2254 if (from != to) 2255 if (from != to)
2255 { 2256 {
2256 eassert (tb != b || to < from); 2257 eassert (tb != b || to < from);
2257 memmove (to, from, nbytes + GC_STRING_EXTRA); 2258 memmove (to, from, size + GC_STRING_EXTRA);
2258 to->string->u.s.data = SDATA_DATA (to); 2259 to->string->u.s.data
2260 = ptr_bounds_clip (SDATA_DATA (to), nbytes + 1);
2259 } 2261 }
2260 2262
2261 /* Advance past the sdata we copied to. */ 2263 /* Advance past the sdata we copied to. */
@@ -3038,6 +3040,7 @@ static EMACS_INT total_vector_slots, total_free_vector_slots;
3038static void 3040static void
3039setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes) 3041setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
3040{ 3042{
3043 v = ptr_bounds_clip (v, nbytes);
3041 eassume (header_size <= nbytes); 3044 eassume (header_size <= nbytes);
3042 ptrdiff_t nwords = (nbytes - header_size) / word_size; 3045 ptrdiff_t nwords = (nbytes - header_size) / word_size;
3043 XSETPVECTYPESIZE (v, PVEC_FREE, 0, nwords); 3046 XSETPVECTYPESIZE (v, PVEC_FREE, 0, nwords);
@@ -3347,7 +3350,7 @@ allocate_vectorlike (ptrdiff_t len)
3347 3350
3348 MALLOC_UNBLOCK_INPUT; 3351 MALLOC_UNBLOCK_INPUT;
3349 3352
3350 return p; 3353 return ptr_bounds_clip (p, nbytes);
3351 } 3354 }
3352} 3355}
3353 3356
@@ -5358,7 +5361,7 @@ pure_alloc (size_t size, int type)
5358 pure_bytes_used = pure_bytes_used_lisp + pure_bytes_used_non_lisp; 5361 pure_bytes_used = pure_bytes_used_lisp + pure_bytes_used_non_lisp;
5359 5362
5360 if (pure_bytes_used <= pure_size) 5363 if (pure_bytes_used <= pure_size)
5361 return result; 5364 return ptr_bounds_clip (result, size);
5362 5365
5363 /* Don't allocate a large amount here, 5366 /* Don't allocate a large amount here,
5364 because it might get mmap'd and then its address 5367 because it might get mmap'd and then its address
@@ -5443,7 +5446,7 @@ find_string_data_in_pure (const char *data, ptrdiff_t nbytes)
5443 /* Check the remaining characters. */ 5446 /* Check the remaining characters. */
5444 if (memcmp (data, non_lisp_beg + start, nbytes) == 0) 5447 if (memcmp (data, non_lisp_beg + start, nbytes) == 0)
5445 /* Found. */ 5448 /* Found. */
5446 return non_lisp_beg + start; 5449 return ptr_bounds_clip (non_lisp_beg + start, nbytes + 1);
5447 5450
5448 start += last_char_skip; 5451 start += last_char_skip;
5449 } 5452 }
diff --git a/src/bytecode.c b/src/bytecode.c
index 8746568f166..78207f776c1 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
24#include "character.h" 24#include "character.h"
25#include "buffer.h" 25#include "buffer.h"
26#include "keyboard.h" 26#include "keyboard.h"
27#include "ptr-bounds.h"
27#include "syntax.h" 28#include "syntax.h"
28#include "window.h" 29#include "window.h"
29 30
@@ -363,13 +364,15 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
363 unsigned char quitcounter = 1; 364 unsigned char quitcounter = 1;
364 EMACS_INT stack_items = XFASTINT (maxdepth) + 1; 365 EMACS_INT stack_items = XFASTINT (maxdepth) + 1;
365 USE_SAFE_ALLOCA; 366 USE_SAFE_ALLOCA;
366 Lisp_Object *stack_base; 367 void *alloc;
367 SAFE_ALLOCA_LISP_EXTRA (stack_base, stack_items, bytestr_length); 368 SAFE_ALLOCA_LISP_EXTRA (alloc, stack_items, bytestr_length);
368 Lisp_Object *stack_lim = stack_base + stack_items; 369 ptrdiff_t item_bytes = stack_items * word_size;
370 Lisp_Object *stack_base = ptr_bounds_clip (alloc, item_bytes);
369 Lisp_Object *top = stack_base; 371 Lisp_Object *top = stack_base;
370 memcpy (stack_lim, SDATA (bytestr), bytestr_length); 372 Lisp_Object *stack_lim = stack_base + stack_items;
371 void *void_stack_lim = stack_lim; 373 unsigned char *bytestr_data = alloc;
372 unsigned char const *bytestr_data = void_stack_lim; 374 bytestr_data = ptr_bounds_clip (bytestr_data + item_bytes, bytestr_length);
375 memcpy (bytestr_data, SDATA (bytestr), bytestr_length);
373 unsigned char const *pc = bytestr_data; 376 unsigned char const *pc = bytestr_data;
374 ptrdiff_t count = SPECPDL_INDEX (); 377 ptrdiff_t count = SPECPDL_INDEX ();
375 378
diff --git a/src/callint.c b/src/callint.c
index 5d88082e38d..df26e4abb51 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21#include <config.h> 21#include <config.h>
22 22
23#include "lisp.h" 23#include "lisp.h"
24#include "ptr-bounds.h"
24#include "character.h" 25#include "character.h"
25#include "buffer.h" 26#include "buffer.h"
26#include "keyboard.h" 27#include "keyboard.h"
@@ -494,6 +495,9 @@ invoke it. If KEYS is omitted or nil, the return value of
494 varies = (signed char *) (visargs + nargs); 495 varies = (signed char *) (visargs + nargs);
495 496
496 memclear (args, nargs * (2 * word_size + 1)); 497 memclear (args, nargs * (2 * word_size + 1));
498 args = ptr_bounds_clip (args, nargs * sizeof *args);
499 visargs = ptr_bounds_clip (visargs, nargs * sizeof *visargs);
500 varies = ptr_bounds_clip (varies, nargs * sizeof *varies);
497 501
498 if (!NILP (enable)) 502 if (!NILP (enable))
499 specbind (Qenable_recursive_minibuffers, Qt); 503 specbind (Qenable_recursive_minibuffers, Qt);
diff --git a/src/dispnew.c b/src/dispnew.c
index b0fc5c31fa1..7fea867f660 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -25,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
25#include <unistd.h> 25#include <unistd.h>
26 26
27#include "lisp.h" 27#include "lisp.h"
28#include "ptr-bounds.h"
28#include "termchar.h" 29#include "termchar.h"
29/* cm.h must come after dispextern.h on Windows. */ 30/* cm.h must come after dispextern.h on Windows. */
30#include "dispextern.h" 31#include "dispextern.h"
@@ -4652,6 +4653,11 @@ scrolling (struct frame *frame)
4652 unsigned *new_hash = old_hash + height; 4653 unsigned *new_hash = old_hash + height;
4653 int *draw_cost = (int *) (new_hash + height); 4654 int *draw_cost = (int *) (new_hash + height);
4654 int *old_draw_cost = draw_cost + height; 4655 int *old_draw_cost = draw_cost + height;
4656 old_hash = ptr_bounds_clip (old_hash, height * sizeof *old_hash);
4657 new_hash = ptr_bounds_clip (new_hash, height * sizeof *new_hash);
4658 draw_cost = ptr_bounds_clip (draw_cost, height * sizeof *draw_cost);
4659 old_draw_cost = ptr_bounds_clip (old_draw_cost,
4660 height * sizeof *old_draw_cost);
4655 4661
4656 eassert (current_matrix); 4662 eassert (current_matrix);
4657 4663
diff --git a/src/editfns.c b/src/editfns.c
index 084d92346f5..6ab26876a88 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -56,6 +56,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
56 56
57#include "composite.h" 57#include "composite.h"
58#include "intervals.h" 58#include "intervals.h"
59#include "ptr-bounds.h"
59#include "character.h" 60#include "character.h"
60#include "buffer.h" 61#include "buffer.h"
61#include "coding.h" 62#include "coding.h"
@@ -4208,9 +4209,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4208 ptrdiff_t nspec_bound = SCHARS (args[0]) >> 1; 4209 ptrdiff_t nspec_bound = SCHARS (args[0]) >> 1;
4209 4210
4210 /* Allocate the info and discarded tables. */ 4211 /* Allocate the info and discarded tables. */
4211 ptrdiff_t alloca_size; 4212 ptrdiff_t info_size, alloca_size;
4212 if (INT_MULTIPLY_WRAPV (nspec_bound, sizeof *info, &alloca_size) 4213 if (INT_MULTIPLY_WRAPV (nspec_bound, sizeof *info, &info_size)
4213 || INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size) 4214 || INT_ADD_WRAPV (formatlen, info_size, &alloca_size)
4214 || SIZE_MAX < alloca_size) 4215 || SIZE_MAX < alloca_size)
4215 memory_full (SIZE_MAX); 4216 memory_full (SIZE_MAX);
4216 info = SAFE_ALLOCA (alloca_size); 4217 info = SAFE_ALLOCA (alloca_size);
@@ -4218,6 +4219,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4218 string was not copied into the output. 4219 string was not copied into the output.
4219 It is 2 if byte I was not the first byte of its character. */ 4220 It is 2 if byte I was not the first byte of its character. */
4220 char *discarded = (char *) &info[nspec_bound]; 4221 char *discarded = (char *) &info[nspec_bound];
4222 info = ptr_bounds_clip (info, info_size);
4223 discarded = ptr_bounds_clip (discarded, formatlen);
4221 memset (discarded, 0, formatlen); 4224 memset (discarded, 0, formatlen);
4222 4225
4223 /* Try to determine whether the result should be multibyte. 4226 /* Try to determine whether the result should be multibyte.
diff --git a/src/emacs.c b/src/emacs.c
index 5a6b896ef47..9dd060fd3dd 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -83,6 +83,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
83#include "charset.h" 83#include "charset.h"
84#include "composite.h" 84#include "composite.h"
85#include "dispextern.h" 85#include "dispextern.h"
86#include "ptr-bounds.h"
86#include "regex.h" 87#include "regex.h"
87#include "sheap.h" 88#include "sheap.h"
88#include "syntax.h" 89#include "syntax.h"
diff --git a/src/frame.c b/src/frame.c
index 5bafbeddcce..94ec9fbdc7d 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -35,6 +35,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
35#include "buffer.h" 35#include "buffer.h"
36/* These help us bind and responding to switch-frame events. */ 36/* These help us bind and responding to switch-frame events. */
37#include "keyboard.h" 37#include "keyboard.h"
38#include "ptr-bounds.h"
38#include "frame.h" 39#include "frame.h"
39#include "blockinput.h" 40#include "blockinput.h"
40#include "termchar.h" 41#include "termchar.h"
@@ -4812,6 +4813,8 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li
4812 USE_SAFE_ALLOCA; 4813 USE_SAFE_ALLOCA;
4813 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize); 4814 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4814 char *class_key = name_key + name_keysize; 4815 char *class_key = name_key + name_keysize;
4816 name_key = ptr_bounds_clip (name_key, name_keysize);
4817 class_key = ptr_bounds_clip (class_key, class_keysize);
4815 4818
4816 /* Start with emacs.FRAMENAME for the name (the specific one) 4819 /* Start with emacs.FRAMENAME for the name (the specific one)
4817 and with `Emacs' for the class key (the general one). */ 4820 and with `Emacs' for the class key (the general one). */
@@ -4890,6 +4893,8 @@ x_get_resource_string (const char *attribute, const char *class)
4890 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2; 4893 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4891 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize); 4894 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4892 char *class_key = name_key + name_keysize; 4895 char *class_key = name_key + name_keysize;
4896 name_key = ptr_bounds_clip (name_key, name_keysize);
4897 class_key = ptr_bounds_clip (class_key, class_keysize);
4893 4898
4894 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute); 4899 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4895 sprintf (class_key, "%s.%s", EMACS_CLASS, class); 4900 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
diff --git a/src/fringe.c b/src/fringe.c
index 087ef33434d..a5581173743 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
24 24
25#include "lisp.h" 25#include "lisp.h"
26#include "frame.h" 26#include "frame.h"
27#include "ptr-bounds.h"
27#include "window.h" 28#include "window.h"
28#include "dispextern.h" 29#include "dispextern.h"
29#include "buffer.h" 30#include "buffer.h"
@@ -1591,7 +1592,9 @@ If BITMAP already exists, the existing definition is replaced. */)
1591 fb.dynamic = true; 1592 fb.dynamic = true;
1592 1593
1593 xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW); 1594 xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW);
1594 fb.bits = b = (unsigned short *) (xfb + 1); 1595 fb.bits = b = ((unsigned short *)
1596 ptr_bounds_clip (xfb + 1, fb.height * BYTES_PER_BITMAP_ROW));
1597 xfb = ptr_bounds_clip (xfb, sizeof *xfb);
1595 memset (b, 0, fb.height); 1598 memset (b, 0, fb.height);
1596 1599
1597 j = 0; 1600 j = 0;
diff --git a/src/gmalloc.c b/src/gmalloc.c
index 97ab76561f9..99cb967e539 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -203,7 +203,8 @@ extern size_t _bytes_free;
203 203
204/* Internal versions of `malloc', `realloc', and `free' 204/* Internal versions of `malloc', `realloc', and `free'
205 used when these functions need to call each other. 205 used when these functions need to call each other.
206 They are the same but don't call the hooks. */ 206 They are the same but don't call the hooks
207 and don't bound the resulting pointers. */
207extern void *_malloc_internal (size_t); 208extern void *_malloc_internal (size_t);
208extern void *_realloc_internal (void *, size_t); 209extern void *_realloc_internal (void *, size_t);
209extern void _free_internal (void *); 210extern void _free_internal (void *);
@@ -921,7 +922,8 @@ malloc (size_t size)
921 among multiple threads. We just leave it for compatibility with 922 among multiple threads. We just leave it for compatibility with
922 glibc malloc (i.e., assignments to gmalloc_hook) for now. */ 923 glibc malloc (i.e., assignments to gmalloc_hook) for now. */
923 hook = gmalloc_hook; 924 hook = gmalloc_hook;
924 return (hook != NULL ? *hook : _malloc_internal) (size); 925 void *result = (hook ? hook : _malloc_internal) (size);
926 return ptr_bounds_clip (result, size);
925} 927}
926 928
927#if !(defined (_LIBC) || defined (HYBRID_MALLOC)) 929#if !(defined (_LIBC) || defined (HYBRID_MALLOC))
@@ -1434,7 +1436,8 @@ realloc (void *ptr, size_t size)
1434 return NULL; 1436 return NULL;
1435 1437
1436 hook = grealloc_hook; 1438 hook = grealloc_hook;
1437 return (hook != NULL ? *hook : _realloc_internal) (ptr, size); 1439 void *result = (hook ? hook : _realloc_internal) (ptr, size);
1440 return ptr_bounds_clip (result, size);
1438} 1441}
1439/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. 1442/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
1440 1443
@@ -1608,6 +1611,7 @@ aligned_alloc (size_t alignment, size_t size)
1608 { 1611 {
1609 l->exact = result; 1612 l->exact = result;
1610 result = l->aligned = (char *) result + adj; 1613 result = l->aligned = (char *) result + adj;
1614 result = ptr_bounds_clip (result, size);
1611 } 1615 }
1612 UNLOCK_ALIGNED_BLOCKS (); 1616 UNLOCK_ALIGNED_BLOCKS ();
1613 if (l == NULL) 1617 if (l == NULL)
diff --git a/src/lisp.h b/src/lisp.h
index 8947c59077e..56545b70946 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -916,9 +916,14 @@ INLINE Lisp_Object
916make_lisp_symbol (struct Lisp_Symbol *sym) 916make_lisp_symbol (struct Lisp_Symbol *sym)
917{ 917{
918#ifdef __CHKP__ 918#ifdef __CHKP__
919 char *symoffset = (char *) sym - (intptr_t) lispsym; 919 /* Although this should use '__builtin___bnd_narrow_ptr_bounds (sym,
920 sym, sizeof *sym)', that would run afoul of GCC bug 83251
921 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83251>. */
922 char *addr = __builtin___bnd_set_ptr_bounds (sym, sizeof *sym);
923 char *symoffset = addr - (intptr_t) lispsym;
920#else 924#else
921 /* If !__CHKP__ this is equivalent, and is a bit faster as of GCC 7. */ 925 /* If !__CHKP__, GCC 7 x86-64 generates faster code if lispsym is
926 cast to char * rather than to intptr_t. */
922 char *symoffset = (char *) ((char *) sym - (char *) lispsym); 927 char *symoffset = (char *) ((char *) sym - (char *) lispsym);
923#endif 928#endif
924 Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset); 929 Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
diff --git a/src/ptr-bounds.h b/src/ptr-bounds.h
index 54979824c05..76740da3d33 100644
--- a/src/ptr-bounds.h
+++ b/src/ptr-bounds.h
@@ -17,6 +17,18 @@ GNU General Public License for more details.
17You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20/* Pointer bounds checking is a no-op unless running on hardware
21 supporting Intel MPX (Intel Skylake or better). Also, it requires
22 GCC 5 and Linux kernel 3.19, or later. Configure with
23 CFLAGS='-fcheck-pointer-bounds -mmpx', perhaps with
24 -fchkp-first-field-has-own-bounds thrown in.
25
26 Although pointer bounds checking can help during debugging, it is
27 disabled by default because it hurts performance significantly.
28 The checking does not detect all pointer errors. For example, a
29 dumped Emacs might not detect a bounds violation of a pointer that
30 was created before Emacs was dumped. */
31
20#ifndef PTR_BOUNDS_H 32#ifndef PTR_BOUNDS_H
21#define PTR_BOUNDS_H 33#define PTR_BOUNDS_H
22 34
@@ -26,6 +38,19 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26 return their first argument. These macros return either void *, or 38 return their first argument. These macros return either void *, or
27 the same type as their first argument. */ 39 the same type as their first argument. */
28 40
41INLINE_HEADER_BEGIN
42
43/* Return a copy of P, with bounds narrowed to [P, P + N). */
44#ifdef __CHKP__
45INLINE void *
46ptr_bounds_clip (void const *p, size_t n)
47{
48 return __builtin___bnd_narrow_ptr_bounds (p, p, n);
49}
50#else
51# define ptr_bounds_clip(p, n) ((void) (size_t) {n}, p)
52#endif
53
29/* Return a copy of P, but with the bounds of Q. */ 54/* Return a copy of P, but with the bounds of Q. */
30#ifdef __CHKP__ 55#ifdef __CHKP__
31# define ptr_bounds_copy(p, q) __builtin___bnd_copy_ptr_bounds (p, q) 56# define ptr_bounds_copy(p, q) __builtin___bnd_copy_ptr_bounds (p, q)
@@ -49,4 +74,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
49# define ptr_bounds_set(p, n) ((void) (size_t) {n}, p) 74# define ptr_bounds_set(p, n) ((void) (size_t) {n}, p)
50#endif 75#endif
51 76
77INLINE_HEADER_END
78
52#endif /* PTR_BOUNDS_H */ 79#endif /* PTR_BOUNDS_H */