analyzer: fix false leak involving params [PR98969]
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 17 Feb 2021 15:37:16 +0000 (10:37 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 17 Feb 2021 15:37:16 +0000 (10:37 -0500)
commite0139b2a912585496f23c352f0e2c56895f78fbf
tree3f185403a60a6a3581ea0fa2131e842013925587
parent366cf1127a547ff77024a551abb01bb1a6e963cd
analyzer: fix false leak involving params [PR98969]

This patch updates the svalue liveness code so that the initial value
of parameters at top-level functions to the analysis are treated as
live (since the values are presumably still live within the
outside-of-the-analysis calling code).

This fixes the false leak in PR analyzer/98969 seen on:

void
test (long int i)
{
  struct foo *f = (struct foo *)i;
  f->expr = __builtin_malloc (1024);
}

since the calling code can presumably still access the allocated
buffer via:
  ((struct foo *)i)->expr

The patch also removes the expected leak warnings from
g++.dg/analyzer/pr99064.C and gcc.dg/analyzer/pr96841.c, which now
appear to me to be false positives.

gcc/analyzer/ChangeLog:
PR analyzer/98969
* constraint-manager.cc (dead_svalue_purger::should_purge_p):
Update for change to svalue::live_p.
* program-state.cc (sm_state_map::on_liveness_change): Likewise.
(program_state::detect_leaks): Likewise.
* region-model-reachability.cc (reachable_regions::init_cluster):
When dealing with a symbolic region, if the underlying pointer is
implicitly live, add the region to the reachable regions.
* region-model.cc (region_model::compare_initial_and_pointer):
Move logic for detecting initial values of params to
initial_svalue::initial_value_of_param_p.
* svalue.cc (svalue::live_p): Convert "live_svalues" from a
reference to a pointer; support it being NULL.
(svalue::implicitly_live_p): Convert first param from a
refererence to a pointer.
(region_svalue::implicitly_live_p): Likewise.
(constant_svalue::implicitly_live_p): Likewise.
(initial_svalue::implicitly_live_p): Likewise.  Treat the initial
values of params for the top level frame as still live.
(initial_svalue::initial_value_of_param_p): New function, taken
from a test in region_model::compare_initial_and_pointer.
(unaryop_svalue::implicitly_live_p): Convert first param from a
refererence to a pointer.
(binop_svalue::implicitly_live_p): Likewise.
(sub_svalue::implicitly_live_p): Likewise.
(unmergeable_svalue::implicitly_live_p): Likewise.
* svalue.h (svalue::live_p): Likewise.
(svalue::implicitly_live_p): Likewise.
(region_svalue::implicitly_live_p): Likewise.
(constant_svalue::implicitly_live_p): Likewise.
(initial_svalue::implicitly_live_p): Likewise.
(initial_svalue::initial_value_of_param_p): New decl.
(unaryop_svalue::implicitly_live_p): Convert first param from a
refererence to a pointer.
(binop_svalue::implicitly_live_p): Likewise.
(sub_svalue::implicitly_live_p): Likewise.
(unmergeable_svalue::implicitly_live_p): Likewise.

gcc/testsuite/ChangeLog:
PR analyzer/98969
* g++.dg/analyzer/pr99064.C: Convert dg-bogus to dg-warning.
* gcc.dg/analyzer/pr96841.c: Add -Wno-analyzer-too-complex to
options.  Remove false leak directive.
* gcc.dg/analyzer/pr98969.c (test_1): Remove xfail from leak
false positive.
(test_3): New.
gcc/analyzer/constraint-manager.cc
gcc/analyzer/program-state.cc
gcc/analyzer/region-model-reachability.cc
gcc/analyzer/region-model.cc
gcc/analyzer/svalue.cc
gcc/analyzer/svalue.h
gcc/testsuite/g++.dg/analyzer/pr99064.C
gcc/testsuite/gcc.dg/analyzer/pr96841.c
gcc/testsuite/gcc.dg/analyzer/pr98969.c