diff options
| author | Paul Eggert | 2017-12-09 13:57:38 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-12-12 15:17:12 -0800 |
| commit | 4295050e1194af13afa26403dd3ebdff80824ae0 (patch) | |
| tree | 354002f3c84f4d8341bb07c5f68529f660a9a405 | |
| parent | 881abfc7fb55db2d00adf352100cc58a6a86c176 (diff) | |
| download | emacs-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.
| -rw-r--r-- | src/alloc.c | 31 | ||||
| -rw-r--r-- | src/bytecode.c | 15 | ||||
| -rw-r--r-- | src/callint.c | 4 | ||||
| -rw-r--r-- | src/dispnew.c | 6 | ||||
| -rw-r--r-- | src/editfns.c | 9 | ||||
| -rw-r--r-- | src/emacs.c | 1 | ||||
| -rw-r--r-- | src/frame.c | 5 | ||||
| -rw-r--r-- | src/fringe.c | 5 | ||||
| -rw-r--r-- | src/gmalloc.c | 10 | ||||
| -rw-r--r-- | src/lisp.h | 9 | ||||
| -rw-r--r-- | src/ptr-bounds.h | 27 |
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; | |||
| 3038 | static void | 3040 | static void |
| 3039 | setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes) | 3041 | setup_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. */ | ||
| 207 | extern void *_malloc_internal (size_t); | 208 | extern void *_malloc_internal (size_t); |
| 208 | extern void *_realloc_internal (void *, size_t); | 209 | extern void *_realloc_internal (void *, size_t); |
| 209 | extern void _free_internal (void *); | 210 | extern 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 | |||
| 916 | make_lisp_symbol (struct Lisp_Symbol *sym) | 916 | make_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. | |||
| 17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | 18 | along 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 | ||
| 41 | INLINE_HEADER_BEGIN | ||
| 42 | |||
| 43 | /* Return a copy of P, with bounds narrowed to [P, P + N). */ | ||
| 44 | #ifdef __CHKP__ | ||
| 45 | INLINE void * | ||
| 46 | ptr_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 | ||
| 77 | INLINE_HEADER_END | ||
| 78 | |||
| 52 | #endif /* PTR_BOUNDS_H */ | 79 | #endif /* PTR_BOUNDS_H */ |