analyzer: fix leak false positives on "*UNKNOWN = PTR;" [PR108252]
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 11 Jan 2023 21:27:06 +0000 (16:27 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 11 Jan 2023 21:27:06 +0000 (16:27 -0500)
commit688fc162b76dc6747a30fcfd470f4770da0f4924
treeff0f5ea0fcfdc97d7508791b82793a27de1128f9
parent23b4ce18379cd336d99d7c71701be28118905b57
analyzer: fix leak false positives on "*UNKNOWN = PTR;" [PR108252]

PR analyzer/108252 reports a false positive from -Wanalyzer-malloc-leak on
code like this:

  *ptr_ptr = strdup(EXPR);

where ptr_ptr is an UNKNOWN_VALUE.

When we handle:
  *UNKNOWN = PTR;
store::set_value normally marks *PTR as having escaped, and this means
we don't report PTR as leaking when the last usage of PTR is lost.

However this only works for cases where PTR is a region_svalue.
In the example in the bug, it's a conjured_svalue, rather than a
region_svalue.  A similar problem can arise for FDs, which aren't
pointers.

This patch fixes the bug by updating store::set_value to mark any
values stored via *UNKNOWN = VAL as not leaking.

Additionally, sm-malloc.cc's known_allocator_p hardcodes strdup and
strndup as allocators (and thus transitioning their result to
"unchecked"), but we don't implement known_functions for these, leading
to the LHS being a CONJURED_SVALUE, rather than a region_svalue to a
heap-allocated region.  A similar issue happens with functions marked
with __attribute__((malloc)).  As part of a "belt and braces" fix, the
patch also updates the handling of these functions, so that they use
heap-allocated regions.

gcc/analyzer/ChangeLog:
PR analyzer/108252
* kf.cc (class kf_strdup): New.
(class kf_strndup): New.
(register_known_functions): Register them.
* region-model.cc (region_model::on_call_pre): Use
&HEAP_ALLOCATED_REGION for the default result of an external
function with the "malloc" attribute, rather than CONJURED_SVALUE.
(region_model::get_or_create_region_for_heap_alloc): Allow
"size_in_bytes" to be NULL.
* store.cc (store::set_value): When handling *UNKNOWN = VAL,
mark VAL as "maybe bound".

gcc/testsuite/ChangeLog:
PR analyzer/108252
* gcc.dg/analyzer/attr-malloc-pr108252.c: New test.
* gcc.dg/analyzer/fd-leak-pr108252.c: New test.
* gcc.dg/analyzer/flex-with-call-summaries.c: Remove xfail from
warning false +ve directives.
* gcc.dg/analyzer/pr103217-2.c: Add -Wno-analyzer-too-complex.
* gcc.dg/analyzer/pr103217-3.c: Likewise.
* gcc.dg/analyzer/strdup-pr108252.c: New test.
* gcc.dg/analyzer/strndup-pr108252.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/analyzer/kf.cc
gcc/analyzer/region-model.cc
gcc/analyzer/store.cc
gcc/testsuite/gcc.dg/analyzer/attr-malloc-pr108252.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/fd-leak-pr108252.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/flex-with-call-summaries.c
gcc/testsuite/gcc.dg/analyzer/pr103217-2.c
gcc/testsuite/gcc.dg/analyzer/pr103217-3.c
gcc/testsuite/gcc.dg/analyzer/strdup-pr108252.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/strndup-pr108252.c [new file with mode: 0644]