From 8f6e9ffcc6231cfd4ae6c0a8b6e1d11beb59dc58 Mon Sep 17 00:00:00 2001 From: Corey Farrell Date: Mon, 18 Jul 2016 23:46:19 -0400 Subject: [PATCH] Add conditional support for noreturn functions. This adds support for tagging functions with the noreturn attribute. If DO_CRASH is enabled then ast_do_crash never returns. If AST_DEVMODE and DO_CRASH are enabled then failed assertions never return. This can resolve a large number of false positives with static analyzers. ASTERISK-26220 #close Change-Id: Icfb61e5fe54574eced4c3e88b317244f467ec753 --- configure | 78 ++++++++++++++++++++++++++++++-- configure.ac | 1 + include/asterisk/autoconfig.h.in | 3 ++ include/asterisk/compiler.h | 6 +++ include/asterisk/utils.h | 9 +++- main/utils.c | 4 +- 6 files changed, 92 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 6d3faf2048..fab78d0186 100755 --- a/configure +++ b/configure @@ -14150,7 +14150,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -14196,7 +14196,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -14220,7 +14220,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -14265,7 +14265,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -14289,7 +14289,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -18026,6 +18026,74 @@ CFLAGS="$saved_CFLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler 'attribute noreturn' support" >&5 +$as_echo_n "checking for compiler 'attribute noreturn' support... " >&6; } +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Wall -Wno-unused -Werror" + + +if test "xnoreturn" = "x" +then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + void __attribute__((noreturn)) *test(void *muffin, ...) {return (void *) 0;} +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +cat >>confdefs.h <<_ACEOF +#define HAVE_ATTRIBUTE_noreturn 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + void __attribute__((noreturn)) *test(void *muffin, ...) ; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +cat >>confdefs.h <<_ACEOF +#define HAVE_ATTRIBUTE_noreturn 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + +CFLAGS="$saved_CFLAGS" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fsanitize=address support" >&5 $as_echo_n "checking for -fsanitize=address support... " >&6; } saved_sanitize_CFLAGS="${CFLAGS}" diff --git a/configure.ac b/configure.ac index dedfd8a2e9..3331f78fee 100644 --- a/configure.ac +++ b/configure.ac @@ -1076,6 +1076,7 @@ AST_GCC_ATTRIBUTE(warn_unused_result) AST_GCC_ATTRIBUTE(may_alias) AST_GCC_ATTRIBUTE(constructor) AST_GCC_ATTRIBUTE(destructor) +AST_GCC_ATTRIBUTE(noreturn,noreturn) AC_MSG_CHECKING(for -fsanitize=address support) saved_sanitize_CFLAGS="${CFLAGS}" diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index 51f0f14629..9d2a84c02c 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -102,6 +102,9 @@ /* Define to 1 if your GCC C compiler supports the 'may_alias' attribute. */ #undef HAVE_ATTRIBUTE_may_alias +/* Define to 1 if your GCC C compiler supports the 'noreturn' attribute. */ +#undef HAVE_ATTRIBUTE_noreturn + /* Define to 1 if your GCC C compiler supports the 'pure' attribute. */ #undef HAVE_ATTRIBUTE_pure diff --git a/include/asterisk/compiler.h b/include/asterisk/compiler.h index 77b5de40e7..6ceaa5f775 100644 --- a/include/asterisk/compiler.h +++ b/include/asterisk/compiler.h @@ -77,6 +77,12 @@ #define attribute_may_alias #endif +#ifdef HAVE_ATTRIBUTE_noreturn +#define attribute_noreturn __attribute__((noreturn)) +#else +#define attribute_noreturn +#endif + /* Some older version of GNU gcc (3.3.5 on OpenBSD 4.3 for example) dont like 'NULL' as sentinel */ #define SENTINEL ((char *)NULL) diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index c7a473732e..c311e9cd5e 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -843,9 +843,14 @@ struct ast_http_digest { */ int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic); +#ifdef DO_CRASH +#define DO_CRASH_NORETURN attribute_noreturn +#else +#define DO_CRASH_NORETURN +#endif #ifdef AST_DEVMODE -void __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function); +void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function); #define ast_assert(a) _ast_assert(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__) static void force_inline _ast_assert(int condition, const char *condition_str, const char *file, int line, const char *function) { @@ -864,7 +869,7 @@ static void force_inline _ast_assert(int condition, const char *condition_str, c * * \return Nothing */ -void ast_do_crash(void); +void DO_CRASH_NORETURN ast_do_crash(void); #include "asterisk/strings.h" diff --git a/main/utils.c b/main/utils.c index 09839752b5..46edf43ea2 100644 --- a/main/utils.c +++ b/main/utils.c @@ -2420,7 +2420,7 @@ char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size) return NULL; } -void ast_do_crash(void) +void DO_CRASH_NORETURN ast_do_crash(void) { #if defined(DO_CRASH) abort(); @@ -2433,7 +2433,7 @@ void ast_do_crash(void) } #if defined(AST_DEVMODE) -void __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function) +void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function) { /* * Attempt to put it into the logger, but hope that at least