From 2eb24b16dac78b3e27769c20502299475fb8dde6 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Mon, 28 Oct 2013 16:25:46 -0500 Subject: [svn-r24368] Issue 8147 - clang's -fcatch-undefined-behavior exposed undefined behavior in the alignment detection algorithm for integers in H5detect.c. Quincey decided to solve it in two steps. First, catch illegal instruction signal in the original algorithm. Second, use POSIX __alignof function to detect alignment if it's available. This checkin is the first step. Tested on wren, jam, ostrich, platypas, and koala. --- src/H5detect.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/H5detect.c b/src/H5detect.c index 3554d50..0f8d051 100644 --- a/src/H5detect.c +++ b/src/H5detect.c @@ -60,9 +60,9 @@ static const char *FileHeader = "\n\ #define MAXDETECT 64 -/* The ALIGNMENT test code may generate the SIGBUS or SIGSEGV signals. We use - * setjmp/longjmp in the signal handlers for recovery. But setjmp/longjmp do - * not necessary restore the signal blocking status while sigsetjmp/siglongjmp +/* The ALIGNMENT test code may generate the SIGBUS, SIGSEGV, or SIGILL signals. + * We use setjmp/longjmp in the signal handlers for recovery. But setjmp/longjmp + * do not necessary restore the signal blocking status while sigsetjmp/siglongjmp * do. If sigsetjmp/siglongjmp are not supported, need to use sigprocmask to * unblock the signal before doing longjmp. */ @@ -139,7 +139,8 @@ static void detect_alignments(void); static size_t align_g[] = {1, 2, 4, 8, 16}; static int align_status_g = 0; /* ALIGNMENT Signal Status */ static int sigbus_handler_called_g = 0; /* how many times called */ -static int sigsegv_handler_called_g = 0; /* how many times called */ +static int sigsegv_handler_called_g = 0;/* how many times called */ +static int sigill_handler_called_g = 0; /* how many times called */ static int signal_handler_tested_g = 0; /* how many times tested */ #if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL) static int verify_signal_handlers(int signum, void (*handler)(int)); @@ -425,6 +426,7 @@ precision (detected_t *d) volatile size_t _ano = 0; \ void (*_handler)(int) = HDsignal(SIGBUS, sigbus_handler); \ void (*_handler2)(int) = HDsignal(SIGSEGV, sigsegv_handler);\ + void (*_handler3)(int) = HDsignal(SIGILL, sigill_handler); \ \ _buf = (char*)HDmalloc(sizeof(TYPE) + align_g[NELMTS(align_g) - 1]); \ if(H5SETJMP(jbuf_g)) _ano++; \ @@ -454,6 +456,7 @@ precision (detected_t *d) HDfree(_buf); \ HDsignal(SIGBUS, _handler); /*restore original handler*/ \ HDsignal(SIGSEGV, _handler2); /*restore original handler*/ \ + HDsignal(SIGILL, _handler3); /*restore original handler*/ \ } #else #define ALIGNMENT(TYPE,INFO) { \ @@ -539,6 +542,42 @@ sigbus_handler(int UNUSED signo) #endif +#if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL) +/*------------------------------------------------------------------------- + * Function: sigill_handler + * + * Purpose: Handler for SIGILL. We use signal() instead of sigaction() + * because it's more portable to non-Posix systems. Although + * it's not nearly as nice to work with, it does the job for + * this simple stuff. + * + * Return: Returns via H5LONGJMP to jbuf_g. + * + * Programmer: Raymond Lu + * 28 October 2013 + * + *------------------------------------------------------------------------- + */ +static void +sigill_handler(int UNUSED signo) +{ +#if !defined(H5HAVE_SIGJMP) && defined(H5_HAVE_SIGPROCMASK) + /* Use sigprocmask to unblock the signal if sigsetjmp/siglongjmp are not */ + /* supported. */ + sigset_t set; + + HDsigemptyset(&set); + HDsigaddset(&set, SIGILL); + HDsigprocmask(SIG_UNBLOCK, &set, NULL); +#endif + + sigill_handler_called_g++; + HDsignal(SIGILL, sigill_handler); + H5LONGJMP(jbuf_g, SIGILL); +} +#endif + + /*------------------------------------------------------------------------- * Function: print_results * -- cgit v0.12