diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2011-09-15 16:59:21 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2011-09-15 16:59:21 +0200 |
commit | 82f8d0bce10403deab704871e638edc24e7933ee (patch) | |
tree | 1afb443b538e0dcdaed4908dac4872a73366f3bb /libc/stdlib/abort.c | |
parent | 200895dab88678b5b4e7d1dac9172be23e92eb31 (diff) |
Defeat compiler optimization which assumes function addresses are never NULL
From email:
A warning for people who can be hit by the same or similar issue:
gcc 4.1.2 with -march=i486 here with -Os and even with -O2 or -O
is "optimizing away" the check
if (_stdio_term)
in libc/stdlib/_atexit.c
which results in a "call 0" and a segfault at exit
if you do not happen to link in stdio.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'libc/stdlib/abort.c')
-rw-r--r-- | libc/stdlib/abort.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c index 3cc796370..a5bac461a 100644 --- a/libc/stdlib/abort.c +++ b/libc/stdlib/abort.c @@ -28,6 +28,17 @@ Cambridge, MA 02139, USA. */ +/* Defeat compiler optimization which assumes function addresses are never NULL */ +static __always_inline int not_null_ptr(const void *p) +{ + const void *q; + __asm__ ("" + : "=r" (q) /* output */ + : "0" (p) /* input */ + ); + return q != 0; +} + /* Our last ditch effort to commit suicide */ #ifdef __UCLIBC_ABORT_INSTRUCTION__ # define ABORT_INSTRUCTION __asm__(__UCLIBC_ABORT_INSTRUCTION__) @@ -68,7 +79,7 @@ void abort(void) * this will attempt to commit all buffered writes. It may also * unbuffer all writable files, or close them outright. * Check the stdio routines for details. */ - if (_stdio_term) { + if (not_null_ptr(_stdio_term)) { _stdio_term(); } #endif |