analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check [PR114408]

gcc/analyzer/ChangeLog:
	PR analyzer/114408
	* engine.cc (impl_run_checkers): Free up any dominance info that
	we may have created.
	* kf.cc (class kf_ubsan_handler): New.
	(register_sanitizer_builtins): New.
	(register_known_functions): Call register_sanitizer_builtins.

gcc/testsuite/ChangeLog:
	PR analyzer/114408
	* c-c++-common/analyzer/deref-before-check-pr114408.c: New test.
	* c-c++-common/ubsan/analyzer-ice-pr114408.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm 2024-03-23 09:52:38 -04:00
parent 2e4b3374cb
commit 80a0cb3745
4 changed files with 60 additions and 0 deletions

View file

@ -6251,6 +6251,13 @@ impl_run_checkers (logger *logger)
eng.get_model_manager ()->dump_untracked_regions ();
delete purge_map;
/* Free up any dominance info that we may have created. */
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
{
function *fun = node->get_fun ();
free_dominance_info (fun, CDI_DOMINATORS);
}
}
/* Handle -fdump-analyzer and -fdump-analyzer-stderr. */

View file

@ -2198,6 +2198,27 @@ register_atomic_builtins (known_function_manager &kfm)
make_unique<kf_atomic_fetch_op> (BIT_IOR_EXPR));
}
/* 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.
Hence we terminate the analysis path at one of these calls. */
class kf_ubsan_handler : public internal_known_function
{
void impl_call_post (const call_details &cd) const final override
{
if (cd.get_ctxt ())
cd.get_ctxt ()->terminate_path ();
}
};
static void
register_sanitizer_builtins (known_function_manager &kfm)
{
kfm.add (BUILT_IN_UBSAN_HANDLE_NONNULL_ARG,
make_unique<kf_ubsan_handler> ());
}
/* Populate KFM with instances of known functions supported by the core of the
analyzer (as opposed to plugins). */
@ -2224,6 +2245,7 @@ register_known_functions (known_function_manager &kfm,
kfm.add (BUILT_IN_STACK_SAVE, make_unique<kf_stack_save> ());
register_atomic_builtins (kfm);
register_sanitizer_builtins (kfm);
register_varargs_builtins (kfm);
}

View file

@ -0,0 +1,22 @@
extern void unknown_returns (const char *p);
extern void unknown_noreturn (const char *p) __attribute__((__noreturn__));
void test_1 (const char *p)
{
if (p)
unknown_returns (p);
__builtin_strcmp ("a", p); /* { dg-message "pointer 'p' is dereferenced here" "" { target c } } */
if (p) /* { dg-warning "check of 'p' for NULL after already dereferencing it" "" { target c } } */
unknown_returns (p);
__builtin_strcmp ("a", p);
}
void test_2 (const char *p)
{
if (p)
unknown_noreturn (p);
__builtin_strcmp ("a", p);
if (p) /* { dg-bogus "check of 'p' for NULL after already dereferencing it" } */
unknown_noreturn (p);
__builtin_strcmp ("a", p);
}

View file

@ -0,0 +1,9 @@
/* { dg-do run } */
/* { dg-require-effective-target analyzer } */
/* { dg-options "-fanalyzer -fsanitize=undefined" } */
int main(){}
int HMAP_unset_copy(const char *key) {
return __builtin_strcmp("a", key) + __builtin_strcmp("a", key);
}