summaryrefslogtreecommitdiff
path: root/src/fns.c
diff options
context:
space:
mode:
authorVibhav Pant <vibhavp@gmail.com>2022-12-19 18:04:05 +0530
committerVibhav Pant <vibhavp@gmail.com>2022-12-19 18:04:05 +0530
commitcb242bf1514ade34ab93b1db1ea7550093ae5839 (patch)
tree05b066f7a16dcba316bb34923bf64a92dca97204 /src/fns.c
parent79b1dede3444c07f943be34867bb2cdac236ab55 (diff)
downloademacs-cb242bf1514ade34ab93b1db1ea7550093ae5839.tar.gz
Add support for additional memory checks using AddressSanitizer.
When Emacs is compiled with AddressSanitizer support, enable poisoning/unpoisoning freed/unused Lisp objects and other internal memory management structures. If enabled, this will mark freed bytes that have been put on free lists for future use and initially allocated memory blocks/chunks as "poisoned", triggering an ASan error if they are accessed improperly. Structures are unpoisoned when they have been taken off their respective free lists. Additionally, add optional macros for performing unaligned loads, which when enabled by defining USE_SANITIZER_UNALIGNED_LOAD will use ASan provided functions for loading from unaligned addresses, which may help catch bugs that AddressSanitizer might otherwise miss. * configure.ac: Check for the existence of address and common sanitizer API headers. * src/lisp.h (UNALIGNED_LOAD_SIZE): New macro. If enabled, and the necessary sanitizer API is available, define it to __sanitizer_unaligned_load(64|32) depending on the word size of the architecture. * src/fns.c [HAVE_FAST_UNALIGNED_ACCESS] (Fstring_lessp): Use 'UNALIGNED_LOAD_SIZE' to perform unaligned loads from the two strings. * src/alloc.c (ASAN_POISON_ABLOCK, ASAN_UNPOISON_ABLOCK) (ASAN_POISON_INTERVAL_BLOCK, ASAN_UNPOISON_INTERVAL_BLOCK) (ASAN_POISON_INTERVAL, ASAN_UNPOISON_INTERVAL) (ASAN_PREPARE_DEAD_SDATA, ASAN_PREPARE_LIVE_SDATA) (ASAN_POISON_SBLOCK_DATA, ASAN_POISON_STRING_BLOCK) (ASAN_UNPOISON_STRING_BLOCK, ASAN_POISON_STRING) (ASAN_UNPOISON_STRING, ASAN_POISON_FLOAT_BLOCK) (ASAN_UNPOISON_FLOAT_BLOCK, ASAN_POISON_FLOAT) (ASAN_UNPOISON_FLOAT, ASAN_POISON_CONS_BLOCK) (ASAN_POISON_CONS, ASAN_UNPOISON_CONS) (ASAN_POISON_VECTOR_CONTENTS, ASAN_UNPOISON_VECTOR_CONTENTS) (ASAN_UNPOISON_VECTOR_BLOCK, ASAN_POISON_SYMBOL_BLOCK) (ASAN_UNPOISON_SYMBOL_BLOCK, ASAN_POISON_SYMBOL) (ASAN_UNPOISON_SYMBOL) [ADDRESS_SANITIZER]: New macros. When address sanitization is enabled, define them to poison/unpoison objects. (lisp_align_malloc): Poison newly allocated blocks on `free_ablock', unpoison ablocks taken from it respectively. (lisp_align_free): Poison individual ablocks when they are put on the free list, unpoison them when an entire `ablocks' chunk is being freed. (make_interval): Poison interval blocks on initial allocation, unpoison individual intervals on allocation and removal from `interval_free_list'. (sweep_intervals): Unpoison interval blocks before sweeping, poison dead/unmarked intervals. (allocate_string): Poison string blocks on initial allocation, unpoison Lisp_Strings on removal from the free list. (allocate_string_data): Poison `sblock' data on initial allocation, unpoison individual `sdata' contents on allocation or removal from the free list. Call `ASAN_PREPARE_LIVE_SDATA' on the new `sdata' struct. (sweep_strings): Unpoison string blocks before sweeping them, poisoning dead strings and their sdata afterwards. (compact_small_strings): Call `ASAN_PREPARE_LIVE_DATA' on the `sdata' to where compacted strings to moved to. (pin_string): Call `ASAN_PREPARE_DEAD_SDATA' on `old_sdata'. (make_float): Poison float blocks on allocation, unpoisoning individual Lisp_Floats on allocation or removal from `float_free_list'. (sweep_floats): Unpoison float blocks before sweeping, poison dead/unmarked floats. (free_cons): Poison `ptr'. (Fcons): Poison cons blocks on allocation, unpoisoning individual Lisp_Cons on allocation or removal from `cons_free_list'. (sweep_conses): Poison dead/unmarked conses. (setup_free_list): Poison vectors put on `vector_free_lists'. (allocate_vector_from_block): Unpoison vectors taken from the free list, poison excess vector bytes when vectors allocated from the free list are larger than requested. (sweep_vectors): Unpoison vector blocks before sweeping them. (Fmake_symbol): Poison symbol blocks on initial allocation, unpoisoning individual Lisp_Symbols on allocation or removal from `symbol_free_list'. (sweep_symbols): Unpoison symbol blocks before sweeping, poisoning dead/unmarked symbols. (live_string_holding, live_cons_holding, live_symbol_holding) (live_float_holding): When compiling with address sanitization and GC poisoning enabled, return NULL if the passed address is poisoned, or if the Lisp object it resides in is poisoned, avoiding a use-after-poison trigger if these functions are called on a pointer that might be referring to a now dead/swept object. * etc/DEBUG: Add information about enabling ASan memory poisoning.
Diffstat (limited to 'src/fns.c')
-rw-r--r--src/fns.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/fns.c b/src/fns.c
index b6e871ad49c..eeb65cadf3f 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -497,8 +497,13 @@ Symbols are also allowed; their print names are used instead. */)
int ws = sizeof (word_t);
const word_t *w1 = (const word_t *) SDATA (string1);
const word_t *w2 = (const word_t *) SDATA (string2);
- while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws])
- b += ws;
+ while (b < nb - ws + 1)
+ {
+ if (UNALIGNED_LOAD_SIZE (w1, b / ws)
+ != UNALIGNED_LOAD_SIZE (w2, b / ws))
+ break;
+ b += ws;
+ }
}
/* Scan forward to the differing byte. */