diff options
| author | Paul Eggert | 2013-12-26 00:57:28 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-12-26 00:57:28 -0800 |
| commit | e76119d7542b19eb03f8d725480cbf98f7fa03d9 (patch) | |
| tree | bdc730dbcd0f54ca25623960feb8df4dfce073b7 /src/alloc.c | |
| parent | 2200a8c91de23f9749d1b3c961c4f8bb3145ddfa (diff) | |
| download | emacs-e76119d7542b19eb03f8d725480cbf98f7fa03d9.tar.gz emacs-e76119d7542b19eb03f8d725480cbf98f7fa03d9.zip | |
Fix core dumps with gcc -fsanitize=address and GNU/Linux.
On my Fedora 19 platform the core dumps were so big that
my desktop became nearly catatonic.
* configure.ac: Check whether addresses are sanitized.
(CANNOT_DUMP): Warn if addresses are sanitized and not CANNOT_DUMP.
(DOUG_LEA_MALLOC): Do not define if addresses are sanitized.
(SYSTEM_MALLOC): Define if addresses are sanitized.
* src/alloc.c (no_sanitize_memcpy) [MAX_SAVE_STACK > 0]: New function.
(Fgarbage_collect) [MAX_SAVE_STACK > 0]: Use it.
(USE_ALIGNED_MALLOC): Do not define if addresses are sanitized.
(mark_memory): Use ATTRIBUTE_NO_SANITIZE_ADDRESS rather than
a clang-only syntax.
* src/conf_post.h (__has_feature): New macro, if not already defined.
(ADDRESS_SANITIZER, ADDRESS_SANITIZER_WORKAROUND)
(ATTRIBUTE_NO_SANITIZE_ADDRESS): New macros.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/src/alloc.c b/src/alloc.c index 447b465a076..14c322a3a64 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -203,7 +203,27 @@ const char *pending_malloc_warning; | |||
| 203 | #if MAX_SAVE_STACK > 0 | 203 | #if MAX_SAVE_STACK > 0 |
| 204 | static char *stack_copy; | 204 | static char *stack_copy; |
| 205 | static ptrdiff_t stack_copy_size; | 205 | static ptrdiff_t stack_copy_size; |
| 206 | #endif | 206 | |
| 207 | /* Copy to DEST a block of memory from SRC of size SIZE bytes, | ||
| 208 | avoiding any address sanitization. */ | ||
| 209 | |||
| 210 | static void * ATTRIBUTE_NO_SANITIZE_ADDRESS | ||
| 211 | no_sanitize_memcpy (void *dest, void const *src, size_t size) | ||
| 212 | { | ||
| 213 | if (! ADDRESS_SANITIZER) | ||
| 214 | return memcpy (dest, src, size); | ||
| 215 | else | ||
| 216 | { | ||
| 217 | size_t i; | ||
| 218 | char *d = dest; | ||
| 219 | char const *s = src; | ||
| 220 | for (i = 0; i < size; i++) | ||
| 221 | d[i] = s[i]; | ||
| 222 | return dest; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | #endif /* MAX_SAVE_STACK > 0 */ | ||
| 207 | 227 | ||
| 208 | static Lisp_Object Qconses; | 228 | static Lisp_Object Qconses; |
| 209 | static Lisp_Object Qsymbols; | 229 | static Lisp_Object Qsymbols; |
| @@ -920,20 +940,26 @@ lisp_free (void *block) | |||
| 920 | /* The entry point is lisp_align_malloc which returns blocks of at most | 940 | /* The entry point is lisp_align_malloc which returns blocks of at most |
| 921 | BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ | 941 | BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ |
| 922 | 942 | ||
| 923 | #if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC | 943 | /* Use aligned_alloc if it or a simple substitute is available. |
| 924 | # define USE_ALIGNED_ALLOC 1 | 944 | Address sanitization breaks aligned allocation, as of gcc 4.8.2 and |
| 945 | clang 3.3 anyway. */ | ||
| 946 | |||
| 947 | #if ! ADDRESS_SANITIZER | ||
| 948 | # if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC | ||
| 949 | # define USE_ALIGNED_ALLOC 1 | ||
| 925 | /* Defined in gmalloc.c. */ | 950 | /* Defined in gmalloc.c. */ |
| 926 | void *aligned_alloc (size_t, size_t); | 951 | void *aligned_alloc (size_t, size_t); |
| 927 | #elif defined HAVE_ALIGNED_ALLOC | 952 | # elif defined HAVE_ALIGNED_ALLOC |
| 928 | # define USE_ALIGNED_ALLOC 1 | 953 | # define USE_ALIGNED_ALLOC 1 |
| 929 | #elif defined HAVE_POSIX_MEMALIGN | 954 | # elif defined HAVE_POSIX_MEMALIGN |
| 930 | # define USE_ALIGNED_ALLOC 1 | 955 | # define USE_ALIGNED_ALLOC 1 |
| 931 | static void * | 956 | static void * |
| 932 | aligned_alloc (size_t alignment, size_t size) | 957 | aligned_alloc (size_t alignment, size_t size) |
| 933 | { | 958 | { |
| 934 | void *p; | 959 | void *p; |
| 935 | return posix_memalign (&p, alignment, size) == 0 ? p : 0; | 960 | return posix_memalign (&p, alignment, size) == 0 ? p : 0; |
| 936 | } | 961 | } |
| 962 | # endif | ||
| 937 | #endif | 963 | #endif |
| 938 | 964 | ||
| 939 | /* BLOCK_ALIGN has to be a power of 2. */ | 965 | /* BLOCK_ALIGN has to be a power of 2. */ |
| @@ -4553,16 +4579,8 @@ mark_maybe_pointer (void *p) | |||
| 4553 | /* Mark Lisp objects referenced from the address range START+OFFSET..END | 4579 | /* Mark Lisp objects referenced from the address range START+OFFSET..END |
| 4554 | or END+OFFSET..START. */ | 4580 | or END+OFFSET..START. */ |
| 4555 | 4581 | ||
| 4556 | static void | 4582 | static void ATTRIBUTE_NO_SANITIZE_ADDRESS |
| 4557 | mark_memory (void *start, void *end) | 4583 | mark_memory (void *start, void *end) |
| 4558 | #if defined (__clang__) && defined (__has_feature) | ||
| 4559 | #if __has_feature(address_sanitizer) | ||
| 4560 | /* Do not allow -faddress-sanitizer to check this function, since it | ||
| 4561 | crosses the function stack boundary, and thus would yield many | ||
| 4562 | false positives. */ | ||
| 4563 | __attribute__((no_address_safety_analysis)) | ||
| 4564 | #endif | ||
| 4565 | #endif | ||
| 4566 | { | 4584 | { |
| 4567 | void **pp; | 4585 | void **pp; |
| 4568 | int i; | 4586 | int i; |
| @@ -5477,7 +5495,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5477 | stack_copy = xrealloc (stack_copy, stack_size); | 5495 | stack_copy = xrealloc (stack_copy, stack_size); |
| 5478 | stack_copy_size = stack_size; | 5496 | stack_copy_size = stack_size; |
| 5479 | } | 5497 | } |
| 5480 | memcpy (stack_copy, stack, stack_size); | 5498 | no_sanitize_memcpy (stack_copy, stack, stack_size); |
| 5481 | } | 5499 | } |
| 5482 | } | 5500 | } |
| 5483 | #endif /* MAX_SAVE_STACK > 0 */ | 5501 | #endif /* MAX_SAVE_STACK > 0 */ |