From a1c925fd41818cb8ad209762739b220efb919d1e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 18 May 2018 15:45:42 -0700 Subject: [PATCH] Port to GCC 8 -fsanitize=undefined MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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. --- src/alloc.c | 32 ++++++++++++++++++++++++-------- src/conf_post.h | 12 ++++++++++++ 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) return (void *) ROUNDUP ((uintptr_t) ptr, alignment); } -/* Extract the pointer hidden within O. Define this as a function, as - functions are cleaner and can be used in debuggers. Also, define - it as a macro if being compiled with GCC without optimization, for - performance in that case. macro_XPNTR is private to this section - of code. */ +/* Define PNTR_ADD and XPNTR as functions, which are cleaner and can + be used in debuggers. Also, define them as macros if + DEFINE_KEY_OPS_AS_MACROS, for performance in that case. + The macro_* macros are private to this section of code. */ + +/* Add a pointer an an integer without complaint about a pointer going + out of range of the underlying array. */ + +#define macro_PNTR_ADD(p, i) ((p) + (i)) + +static char * ATTRIBUTE_NO_SANITIZE_UNDEFINED ATTRIBUTE_UNUSED +PNTR_ADD (char *p, EMACS_UINT i) +{ + return macro_PNTR_ADD (p, i); +} + +#if DEFINE_KEY_OPS_AS_MACROS +# define PNTR_ADD(p, i) macro_PNTR_ADD (p, i) +#endif + +/* Extract the pointer hidden within O. */ #define macro_XPNTR(o) \ ((void *) \ (SYMBOLP (o) \ - ? ((char *) lispsym \ - - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)) \ - + XLI (o)) \ + ? PNTR_ADD ((char *) lispsym, \ + (XLI (o) \ + - ((EMACS_UINT) Lisp_Symbol << (USE_LSB_TAG ? 0 : VALBITS)))) \ : (char *) XLP (o) - (XLI (o) & ~VALMASK))) 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; # define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0) # define __has_attribute_no_address_safety_analysis false # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) +# define __has_attribute_no_sanitize_undefined GNUC_PREREQ (4, 9, 0) #endif /* Simulate __has_builtin on compilers that lack it. It is used only @@ -338,6 +339,17 @@ extern int emacs_setenv_TZ (char const *); # define ATTRIBUTE_NO_SANITIZE_ADDRESS #endif +/* Attribute of functions whose undefined behavior should not be sanitized. */ + +#if __has_attribute (no_sanitize_undefined) +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined)) +#elif __has_attribute (no_sanitize) +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__ ((no_sanitize ("undefined"))) +#else +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + /* gcc -fsanitize=address does not work with vfork in Fedora 25 x86-64. For now, assume that this problem occurs on all platforms. */ #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 return lisp_h_SYMBOLP (x); } -INLINE struct Lisp_Symbol * +INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED (XSYMBOL) (Lisp_Object a) { #if USE_LSB_TAG -- 2.39.5