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.
This commit is contained in:
parent
2200a8c91d
commit
e76119d754
5 changed files with 127 additions and 31 deletions
|
@ -1,3 +1,11 @@
|
|||
2013-12-26 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Fix core dumps with gcc -fsanitize=address and GNU/Linux.
|
||||
* 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.
|
||||
|
||||
2013-12-24 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Automate the procedure for updating copyright year.
|
||||
|
|
45
configure.ac
45
configure.ac
|
@ -1048,6 +1048,21 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
|
|||
|
||||
LDFLAGS="$late_LDFLAGS"
|
||||
|
||||
AC_CACHE_CHECK([whether addresses are sanitized],
|
||||
[emacs_cv_sanitize_address],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#ifndef __has_feature
|
||||
#define __has_feature(f) 0
|
||||
#endif
|
||||
#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
|
||||
#else
|
||||
#error "Addresses are not sanitized."
|
||||
#endif
|
||||
]])],
|
||||
[emacs_cv_sanitize_address=yes],
|
||||
[emacs_cv_sanitize_address=no])])
|
||||
|
||||
dnl The function dump-emacs will not be defined and temacs will do
|
||||
dnl (load "loadup") automatically unless told otherwise.
|
||||
test "x$CANNOT_DUMP" = "x" && CANNOT_DUMP=no
|
||||
|
@ -1055,8 +1070,11 @@ case "$opsys" in
|
|||
your-opsys-here) CANNOT_DUMP=yes ;;
|
||||
esac
|
||||
|
||||
test "$CANNOT_DUMP" = "yes" && \
|
||||
if test "$CANNOT_DUMP" = "yes"; then
|
||||
AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs cannot be dumped on your system.])
|
||||
elif test "$emacs_cv_sanitize_address" = yes; then
|
||||
AC_MSG_WARN([[Addresses are sanitized; suggest CANNOT_DUMP=yes]])
|
||||
fi
|
||||
|
||||
AC_SUBST(CANNOT_DUMP)
|
||||
|
||||
|
@ -1888,20 +1906,21 @@ GNU_MALLOC=yes
|
|||
AC_CACHE_CHECK(
|
||||
[whether malloc is Doug Lea style],
|
||||
[emacs_cv_var_doug_lea_malloc],
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <malloc.h>
|
||||
static void hook (void) {}]],
|
||||
[[malloc_set_state (malloc_get_state ());
|
||||
__after_morecore_hook = hook;
|
||||
__malloc_initialize_hook = hook;]])],
|
||||
[emacs_cv_var_doug_lea_malloc=yes],
|
||||
[emacs_cv_var_doug_lea_malloc=no])])
|
||||
[emacs_cv_var_doug_lea_malloc=no
|
||||
dnl Hooks do not work with address sanitization.
|
||||
if test "$emacs_cv_sanitize_address" != yes; then
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <malloc.h>
|
||||
static void hook (void) {}]],
|
||||
[[malloc_set_state (malloc_get_state ());
|
||||
__after_morecore_hook = hook;
|
||||
__malloc_initialize_hook = hook;]])],
|
||||
[emacs_cv_var_doug_lea_malloc=yes])])
|
||||
fi
|
||||
doug_lea_malloc=$emacs_cv_var_doug_lea_malloc
|
||||
|
||||
|
||||
dnl See comments in aix4-2.h about maybe using system malloc there.
|
||||
system_malloc=no
|
||||
system_malloc=$emacs_cv_sanitize_address
|
||||
case "$opsys" in
|
||||
## darwin ld insists on the use of malloc routines in the System framework.
|
||||
darwin|sol2-10) system_malloc=yes ;;
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
2013-12-26 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
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.
|
||||
* 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.
|
||||
* conf_post.h (__has_feature): New macro, if not already defined.
|
||||
(ADDRESS_SANITIZER, ADDRESS_SANITIZER_WORKAROUND)
|
||||
(ATTRIBUTE_NO_SANITIZE_ADDRESS): New macros.
|
||||
|
||||
2013-12-25 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* w32fns.c (Fw32_shell_execute): Make DOCUMENT absolute only if it
|
||||
|
|
52
src/alloc.c
52
src/alloc.c
|
@ -203,7 +203,27 @@ const char *pending_malloc_warning;
|
|||
#if MAX_SAVE_STACK > 0
|
||||
static char *stack_copy;
|
||||
static ptrdiff_t stack_copy_size;
|
||||
#endif
|
||||
|
||||
/* Copy to DEST a block of memory from SRC of size SIZE bytes,
|
||||
avoiding any address sanitization. */
|
||||
|
||||
static void * ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
no_sanitize_memcpy (void *dest, void const *src, size_t size)
|
||||
{
|
||||
if (! ADDRESS_SANITIZER)
|
||||
return memcpy (dest, src, size);
|
||||
else
|
||||
{
|
||||
size_t i;
|
||||
char *d = dest;
|
||||
char const *s = src;
|
||||
for (i = 0; i < size; i++)
|
||||
d[i] = s[i];
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MAX_SAVE_STACK > 0 */
|
||||
|
||||
static Lisp_Object Qconses;
|
||||
static Lisp_Object Qsymbols;
|
||||
|
@ -920,20 +940,26 @@ lisp_free (void *block)
|
|||
/* The entry point is lisp_align_malloc which returns blocks of at most
|
||||
BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */
|
||||
|
||||
#if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
|
||||
# define USE_ALIGNED_ALLOC 1
|
||||
/* Use aligned_alloc if it or a simple substitute is available.
|
||||
Address sanitization breaks aligned allocation, as of gcc 4.8.2 and
|
||||
clang 3.3 anyway. */
|
||||
|
||||
#if ! ADDRESS_SANITIZER
|
||||
# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
|
||||
# define USE_ALIGNED_ALLOC 1
|
||||
/* Defined in gmalloc.c. */
|
||||
void *aligned_alloc (size_t, size_t);
|
||||
#elif defined HAVE_ALIGNED_ALLOC
|
||||
# define USE_ALIGNED_ALLOC 1
|
||||
#elif defined HAVE_POSIX_MEMALIGN
|
||||
# define USE_ALIGNED_ALLOC 1
|
||||
# elif defined HAVE_ALIGNED_ALLOC
|
||||
# define USE_ALIGNED_ALLOC 1
|
||||
# elif defined HAVE_POSIX_MEMALIGN
|
||||
# define USE_ALIGNED_ALLOC 1
|
||||
static void *
|
||||
aligned_alloc (size_t alignment, size_t size)
|
||||
{
|
||||
void *p;
|
||||
return posix_memalign (&p, alignment, size) == 0 ? p : 0;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* BLOCK_ALIGN has to be a power of 2. */
|
||||
|
@ -4553,16 +4579,8 @@ mark_maybe_pointer (void *p)
|
|||
/* Mark Lisp objects referenced from the address range START+OFFSET..END
|
||||
or END+OFFSET..START. */
|
||||
|
||||
static void
|
||||
static void ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
mark_memory (void *start, void *end)
|
||||
#if defined (__clang__) && defined (__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
/* Do not allow -faddress-sanitizer to check this function, since it
|
||||
crosses the function stack boundary, and thus would yield many
|
||||
false positives. */
|
||||
__attribute__((no_address_safety_analysis))
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
void **pp;
|
||||
int i;
|
||||
|
@ -5477,7 +5495,7 @@ See Info node `(elisp)Garbage Collection'. */)
|
|||
stack_copy = xrealloc (stack_copy, stack_size);
|
||||
stack_copy_size = stack_size;
|
||||
}
|
||||
memcpy (stack_copy, stack, stack_size);
|
||||
no_sanitize_memcpy (stack_copy, stack, stack_size);
|
||||
}
|
||||
}
|
||||
#endif /* MAX_SAVE_STACK > 0 */
|
||||
|
|
|
@ -50,8 +50,19 @@ typedef bool bool_bf;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* When not using Clang, assume its attributes and features are absent. */
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(a) false /* non-clang */
|
||||
# define __has_attribute(a) false
|
||||
#endif
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(a) false
|
||||
#endif
|
||||
|
||||
/* True if addresses are being sanitized. */
|
||||
#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
|
||||
# define ADDRESS_SANITIZER true
|
||||
#else
|
||||
# define ADDRESS_SANITIZER false
|
||||
#endif
|
||||
|
||||
#ifdef DARWIN_OS
|
||||
|
@ -204,6 +215,32 @@ extern void _DebPrint (const char *fmt, ...);
|
|||
|
||||
#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
|
||||
|
||||
/* Work around GCC bug 59600: when a function is inlined, the inlined
|
||||
code may have its addresses sanitized even if the function has the
|
||||
no_sanitize_address attribute. This bug is present in GCC 4.8.2
|
||||
and clang 3.3, the latest releases as of December 2013, and the
|
||||
only platforms known to support address sanitization. When the bug
|
||||
is fixed the #if can be updated accordingly. */
|
||||
#if ADDRESS_SANITIZER
|
||||
# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE
|
||||
#else
|
||||
# define ADDRESS_SANITIZER_WORKAROUND
|
||||
#endif
|
||||
|
||||
/* Attribute of functions whose code should not have addresses
|
||||
sanitized. */
|
||||
|
||||
#if (__has_attribute (no_sanitize_address) \
|
||||
|| 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
|
||||
# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
|
||||
__attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND
|
||||
#elif __has_attribute (no_address_safety_analysis)
|
||||
# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
|
||||
__attribute__ ((no_address_safety_analysis)) ADDRESS_SANITIZER_WORKAROUND
|
||||
#else
|
||||
# define ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
#endif
|
||||
|
||||
/* Some versions of GNU/Linux define noinline in their headers. */
|
||||
#ifdef noinline
|
||||
#undef noinline
|
||||
|
|
Loading…
Add table
Reference in a new issue