diff options
| author | Paul Eggert | 2018-05-18 15:45:42 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-05-18 15:49:48 -0700 |
| commit | a1c925fd41818cb8ad209762739b220efb919d1e (patch) | |
| tree | 4d3c95a065057114a49a9a3435d26479a086d8a1 /src | |
| parent | f4d9fd3dd45f767eca33fbf1beee40da790fa74e (diff) | |
| download | emacs-a1c925fd41818cb8ad209762739b220efb919d1e.tar.gz emacs-a1c925fd41818cb8ad209762739b220efb919d1e.zip | |
Port to GCC 8 -fsanitize=undefined
In GCC 8, gcc -fsanitize=undefined flags the undefined behavior
that Emacs relies on in its XPNTR and XSYMBOL low-level functions.
Disable undefined sanitization in these functions. Although this
disabling doesn’t suffice if DEFINE_KEY_OPS_AS_MACROS is true, it
works for -fsanitize=undefined -DINLINING=0, which is good enough.
* src/alloc.c (macro_PNTR_ADD): New macro.
(PNTR_ADD): New function and macro.
The function disables -fsanitize=undefined.
(macro_XPNTR): Use it.
* src/conf_post.h (ATTRIBUTE_NO_SANITIZE_UNDEFINED): New macro.
* src/lisp.h (XSYMBOL): Disable -fsanitize=undefined.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 32 | ||||
| -rw-r--r-- | src/conf_post.h | 12 | ||||
| -rw-r--r-- | src/lisp.h | 2 |
3 files changed, 37 insertions, 9 deletions
diff --git a/src/alloc.c b/src/alloc.c index 8264e0623cf..231ade5cf80 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -503,18 +503,34 @@ pointer_align (void *ptr, int alignment) | |||
| 503 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); | 503 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | /* Extract the pointer hidden within O. Define this as a function, as | 506 | /* Define PNTR_ADD and XPNTR as functions, which are cleaner and can |
| 507 | functions are cleaner and can be used in debuggers. Also, define | 507 | be used in debuggers. Also, define them as macros if |
| 508 | it as a macro if being compiled with GCC without optimization, for | 508 | DEFINE_KEY_OPS_AS_MACROS, for performance in that case. |
| 509 | performance in that case. macro_XPNTR is private to this section | 509 | The macro_* macros are private to this section of code. */ |
| 510 | of code. */ | 510 | |
| 511 | /* Add a pointer an an integer without complaint about a pointer going | ||
| 512 | out of range of the underlying array. */ | ||
| 513 | |||
| 514 | #define macro_PNTR_ADD(p, i) ((p) + (i)) | ||
| 515 | |||
| 516 | static char * ATTRIBUTE_NO_SANITIZE_UNDEFINED ATTRIBUTE_UNUSED | ||
| 517 | PNTR_ADD (char *p, EMACS_UINT i) | ||
| 518 | { | ||
| 519 | return macro_PNTR_ADD (p, i); | ||
| 520 | } | ||
| 521 | |||
| 522 | #if DEFINE_KEY_OPS_AS_MACROS | ||
| 523 | # define PNTR_ADD(p, i) macro_PNTR_ADD (p, i) | ||
| 524 | #endif | ||
| 525 | |||
| 526 | /* Extract the pointer hidden within O. */ | ||
| 511 | 527 | ||
| 512 | #define macro_XPNTR(o) \ | 528 | #define macro_XPNTR(o) \ |
| 513 | ((void *) \ | 529 | ((void *) \ |
| 514 | (SYMBOLP (o) \ | 530 | (SYMBOLP (o) \ |
| 515 | ? ((char *) lispsym \ | 531 | ? PNTR_ADD ((char *) lispsym, \ |
| 516 | - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)) \ | 532 | (XLI (o) \ |
| 517 | + XLI (o)) \ | 533 | - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)))) \ |
| 518 | : (char *) XLP (o) - (XLI (o) & ~VALMASK))) | 534 | : (char *) XLP (o) - (XLI (o) & ~VALMASK))) |
| 519 | 535 | ||
| 520 | static ATTRIBUTE_UNUSED void * | 536 | static ATTRIBUTE_UNUSED void * |
diff --git a/src/conf_post.h b/src/conf_post.h index 00e283d289c..bf2cfc4f05f 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -67,6 +67,7 @@ typedef bool bool_bf; | |||
| 67 | # define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0) | 67 | # define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0) |
| 68 | # define __has_attribute_no_address_safety_analysis false | 68 | # define __has_attribute_no_address_safety_analysis false |
| 69 | # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) | 69 | # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) |
| 70 | # define __has_attribute_no_sanitize_undefined GNUC_PREREQ (4, 9, 0) | ||
| 70 | #endif | 71 | #endif |
| 71 | 72 | ||
| 72 | /* Simulate __has_builtin on compilers that lack it. It is used only | 73 | /* Simulate __has_builtin on compilers that lack it. It is used only |
| @@ -338,6 +339,17 @@ extern int emacs_setenv_TZ (char const *); | |||
| 338 | # define ATTRIBUTE_NO_SANITIZE_ADDRESS | 339 | # define ATTRIBUTE_NO_SANITIZE_ADDRESS |
| 339 | #endif | 340 | #endif |
| 340 | 341 | ||
| 342 | /* Attribute of functions whose undefined behavior should not be sanitized. */ | ||
| 343 | |||
| 344 | #if __has_attribute (no_sanitize_undefined) | ||
| 345 | # define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined)) | ||
| 346 | #elif __has_attribute (no_sanitize) | ||
| 347 | # define ATTRIBUTE_NO_SANITIZE_UNDEFINED \ | ||
| 348 | __attribute__ ((no_sanitize ("undefined"))) | ||
| 349 | #else | ||
| 350 | # define ATTRIBUTE_NO_SANITIZE_UNDEFINED | ||
| 351 | #endif | ||
| 352 | |||
| 341 | /* gcc -fsanitize=address does not work with vfork in Fedora 25 x86-64. | 353 | /* gcc -fsanitize=address does not work with vfork in Fedora 25 x86-64. |
| 342 | For now, assume that this problem occurs on all platforms. */ | 354 | For now, assume that this problem occurs on all platforms. */ |
| 343 | #if ADDRESS_SANITIZER && !defined vfork | 355 | #if ADDRESS_SANITIZER && !defined vfork |
diff --git a/src/lisp.h b/src/lisp.h index a18b64a588f..ee2e72d32b7 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -900,7 +900,7 @@ INLINE bool | |||
| 900 | return lisp_h_SYMBOLP (x); | 900 | return lisp_h_SYMBOLP (x); |
| 901 | } | 901 | } |
| 902 | 902 | ||
| 903 | INLINE struct Lisp_Symbol * | 903 | INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED |
| 904 | (XSYMBOL) (Lisp_Object a) | 904 | (XSYMBOL) (Lisp_Object a) |
| 905 | { | 905 | { |
| 906 | #if USE_LSB_TAG | 906 | #if USE_LSB_TAG |