Previously the analyzer treated IFN_UBSAN_BOUNDS as a no-op, but the other IFN_UBSAN_* were unrecognized and conservatively treated as having arbitrary behavior.
Treat IFN_UBSAN_NULL and IFN_UBSAN_PTR also as no-ops, which should make -fanalyzer behave better with -fsanitize=undefined. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r15-7626-g58b90139e093ae. gcc/analyzer/ChangeLog: PR analyzer/118300 * kf.cc (class kf_ubsan_bounds): Replace this with... (class kf_ubsan_noop): ...this. (register_sanitizer_builtins): Use it to handle IFN_UBSAN_NULL, IFN_UBSAN_BOUNDS, and IFN_UBSAN_PTR as nop-ops. (register_known_functions): Drop handling of IFN_UBSAN_BOUNDS here, as it's now handled by register_sanitizer_builtins above. gcc/testsuite/ChangeLog: PR analyzer/118300 * gcc.dg/analyzer/ubsan-pr118300.c: New test. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/analyzer/kf.cc | 22 ++++++++++++++----- .../gcc.dg/analyzer/ubsan-pr118300.c | 15 +++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/ubsan-pr118300.c diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc index f3aa2b1b7d25..dceedd4569d3 100644 --- a/gcc/analyzer/kf.cc +++ b/gcc/analyzer/kf.cc @@ -2061,11 +2061,6 @@ private: const private_region m_private_reg; }; -class kf_ubsan_bounds : public internal_known_function -{ - /* Empty. */ -}; - /* Handle calls to functions referenced by __attribute__((malloc(FOO))). */ @@ -2202,6 +2197,13 @@ register_atomic_builtins (known_function_manager &kfm) make_unique<kf_atomic_fetch_op> (BIT_IOR_EXPR)); } +/* Handle calls to the various IFN_UBSAN_* with no return value. + For now, treat these as no-ops. */ + +class kf_ubsan_noop : public internal_known_function +{ +}; + /* Handle calls to the various __builtin___ubsan_handle_*. These can return, but continuing after such a return isn't likely to be interesting to the user of the analyzer. @@ -2219,6 +2221,15 @@ class kf_ubsan_handler : public internal_known_function static void register_sanitizer_builtins (known_function_manager &kfm) { + /* Handle calls to the various IFN_UBSAN_* with no return value. + For now, treat these as no-ops. */ + kfm.add (IFN_UBSAN_NULL, + make_unique<kf_ubsan_noop> ()); + kfm.add (IFN_UBSAN_BOUNDS, + make_unique<kf_ubsan_noop> ()); + kfm.add (IFN_UBSAN_PTR, + make_unique<kf_ubsan_noop> ()); + kfm.add (BUILT_IN_UBSAN_HANDLE_NONNULL_ARG, make_unique<kf_ubsan_handler> ()); } @@ -2236,7 +2247,6 @@ register_known_functions (known_function_manager &kfm, /* Internal fns the analyzer has known_functions for. */ { kfm.add (IFN_BUILTIN_EXPECT, make_unique<kf_expect> ()); - kfm.add (IFN_UBSAN_BOUNDS, make_unique<kf_ubsan_bounds> ()); } /* GCC built-ins that do not correspond to a function diff --git a/gcc/testsuite/gcc.dg/analyzer/ubsan-pr118300.c b/gcc/testsuite/gcc.dg/analyzer/ubsan-pr118300.c new file mode 100644 index 000000000000..87cdc0a37e71 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/ubsan-pr118300.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fsanitize=undefined" } */ + +#include <stdlib.h> + +void test () +{ + int*** ptr = (int ***)malloc(sizeof(int**)); + *ptr = (int **)malloc(sizeof(int*)); /* { dg-warning "dereference of possibly-NULL" } */ + **ptr = (int *)malloc(sizeof(int)); /* { dg-warning "dereference of possibly-NULL" } */ + + free(**ptr); + free(*ptr); + free(ptr); +} -- 2.26.3