Age | Commit message (Collapse) | Author | Files | Lines |
|
|
|
[PR109239]
The patch has this effect on my integration tests of -fanalyzer:
Comparison:
GOOD: 129 (17.70% -> 17.92%)
BAD: 600 -> 591 (-9)
which is purely due to improvements to -Wanalyzer-deref-before-check
on the Linux kernel:
-Wanalyzer-deref-before-check:
GOOD: 1 (4.55% -> 7.69%)
BAD: 21 -> 12 (-9)
Known false positives: 16 -> 10 (-6)
linux-5.10.162: 7 -> 1 (-6)
Suspected false positives: 3 -> 0 (-3)
linux-5.10.162: 3 -> 0 (-3)
gcc/analyzer/ChangeLog:
PR analyzer/109239
* program-point.cc: Include "analyzer/inlining-iterator.h".
(program_point::effectively_intraprocedural_p): New function.
* program-point.h (program_point::effectively_intraprocedural_p):
New decl.
* sm-malloc.cc (deref_before_check::emit): Use it when rejecting
interprocedural cases, so that we reject interprocedural cases
that have become intraprocedural due to inlining.
gcc/testsuite/ChangeLog:
PR analyzer/109239
* gcc.dg/analyzer/deref-before-check-pr109239-linux-bus.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/109094 reports an ICE in the analyzer seen on qemu's
target/i386/tcg/translate.c
The issue turned out to be that when handling a longjmp, the code
to pop the frames was generating an svalue for the result_decl of any
popped frame that had a non-void return type (and discarding it) leading
to "uninit" poisoned_svalue_diagnostic instances being saved since the
result_decl is only set by the greturn stmt. Later, when checking the
feasibility of the path to these diagnostics, m_check_expr was evaluated
in the context of the frame of the longjmp, leading to an attempt to
evaluate the result_decl of each intervening frames whilst in the
context of the topmost frame, leading to an assertion failure in
frame_region::get_region_for_local here:
919 case RESULT_DECL:
920 gcc_assert (DECL_CONTEXT (expr) == m_fun->decl);
921 break;
This patch updates the analyzer's longjmp implementation so that it
doesn't attempt to generate svalues for the result_decls when popping
frames, fixing the assertion failure (and presumably fixing "uninit"
false positives in a release build).
gcc/analyzer/ChangeLog:
PR analyzer/109094
* region-model.cc (region_model::on_longjmp): Pass false for
new "eval_return_svalue" param of pop_frame.
(region_model::pop_frame): Add new "eval_return_svalue" param and
use it to suppress the call to get_rvalue on the result when
needed by on_longjmp.
* region-model.h (region_model::pop_frame): Add new
"eval_return_svalue" param.
gcc/testsuite/ChangeLog:
PR analyzer/109094
* gcc.dg/analyzer/setjmp-pr109094.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
If a bound region gets overwritten with UNKNOWN due to being
possibly-aliased during a write, that could have been the only
region keeping its value live, in which case we could falsely report
a leak. This is hidden somewhat by the "uncertainty" mechanism for
cases where the write happens in the same stmt as the last reference
to the value goes away, but not in the general case, which occurs
in PR analyzer/109059, which falsely complains about a leak whilst
haproxy updates a doubly-linked list.
The whole "uncertainty_t" class seems broken to me now; I think we need
to track (in the store) what values could have escaped to the external
part of the program. We do this to some extent for pointers by tracking
the region as escaped, though we're failing to do this for this case:
even though there could still be other pointers to the region,
eventually they go away; we want to capture the fact that the external
part of the state is still keeping it live. Also, this doesn't work for
non-pointer svalues, such as for detecting file-descriptor leaks.
As both a workaround and a step towards eventually removing
"class uncertainty_t" this patch updates the "mark_region_as_unknown"
code called by possibly-aliased set_value so that when old values are
removed, any base region pointed to them is marked as escaped, fixing
the leak false positive.
The patch has this effect on my integration tests of -fanalyzer:
Comparison:
GOOD: 129 (19.20% -> 20.22%)
BAD: 543 -> 509 (-34)
where there's a big improvement in -Wanalyzer-malloc-leak:
-Wanalyzer-malloc-leak:
GOOD: 61 (45.19% -> 54.95%)
BAD: 74 -> 50 (-24)
Known false positives: 25 -> 2 (-23)
haproxy-2.7.1: 24 -> 1 (-23)
Suspected false positives: 49 -> 48 (-1)
coreutils-9.1: 32 -> 31 (-1)
and some churn in the other warnings:
-Wanalyzer-use-of-uninitialized-value:
GOOD: 0
BAD: 81 -> 80 (-1)
-Wanalyzer-file-leak:
GOOD: 0
BAD: 10 -> 11 (+1)
-Wanalyzer-out-of-bounds:
GOOD: 0
BAD: 24 -> 22 (-2)
gcc/analyzer/ChangeLog:
PR analyzer/109059
* region-model.cc (region_model::mark_region_as_unknown): Gather a
set of maybe-live svalues and call on_maybe_live_values with it.
* store.cc (binding_map::remove_overlapping_bindings): Add new
"maybe_live_values" param; add any removed svalues to it.
(binding_cluster::clobber_region): Add NULL as new param of
remove_overlapping_bindings.
(binding_cluster::mark_region_as_unknown): Add "maybe_live_values"
param and pass it to remove_overlapping_bindings.
(binding_cluster::maybe_get_compound_binding): Add NULL for new
param of binding_map::remove_overlapping_bindings.
(binding_cluster::remove_overlapping_bindings): Add
"maybe_live_values" param and pass to
binding_map::remove_overlapping_bindings.
(store::set_value): Capture a set of maybe-live svalues, and call
on_maybe_live_values with it.
(store::on_maybe_live_values): New.
(store::mark_region_as_unknown): Add "maybe_live_values" param
and pass it to binding_cluster::mark_region_as_unknown.
(store::remove_overlapping_bindings): Pass NULL for new param of
binding_cluster::remove_overlapping_bindings.
* store.h (binding_map::remove_overlapping_bindings): Add
"maybe_live_values" param.
(binding_cluster::mark_region_as_unknown): Likewise.
(binding_cluster::remove_overlapping_bindings): Likewise.
(store::mark_region_as_unknown): Likewise.
(store::on_maybe_live_values): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/109059
* gcc.dg/analyzer/flex-with-call-summaries.c: Remove xfail.
* gcc.dg/analyzer/leak-pr109059-1.c: New test.
* gcc.dg/analyzer/leak-pr109059-2.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Integration testing showed various false positives from
-Wanalyzer-deref-before-check where the expression that's dereferenced
is different from the one that's checked, but the diagnostic is emitted
because they both evaluate to the same symbolic value.
This patch rejects such warnings, unless we have tree expressions for
both and that both tree expressions are "spelled the same way" i.e.
would be printed to the same user-facing string.
gcc/analyzer/ChangeLog:
PR analyzer/108475
PR analyzer/109060
* sm-malloc.cc (deref_before_check::deref_before_check):
Initialize new field m_deref_expr. Assert that arg is non-NULL.
(deref_before_check::emit): Reject cases where the spelling of the
thing that was dereferenced differs from that of what is checked,
or if the dereference expression was not found. Remove code to
handle NULL m_arg.
(deref_before_check::describe_state_change): Remove code to handle
NULL m_arg.
(deref_before_check::describe_final_event): Likewise.
(deref_before_check::sufficiently_similar_p): New.
(deref_before_check::m_deref_expr): New field.
(malloc_state_machine::maybe_complain_about_deref_before_check):
Don't warn if the diag_ptr is NULL.
gcc/testsuite/ChangeLog:
PR analyzer/108475
PR analyzer/109060
* gcc.dg/analyzer/deref-before-check-pr108475-1.c: New test.
* gcc.dg/analyzer/deref-before-check-pr108475-haproxy-tcpcheck.c:
New test.
* gcc.dg/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c:
New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
Previously, the analyzer lacked a known_function implementation of
sprintf, and thus would handle calls to sprintf with the "anything could
happen" fallback.
Whilst working on PR analyzer/107565 I noticed that this was preventing
a lot of genuine memory leaks from being reported for Doom; fixing
thusly.
Integration testing of the effect of the patch shows a big increase in
true positives due to the case mentioned in Doom, and one new false
positive (in pcre2), which I'm tracking as PR analyzer/109014.
Comparison:
GOOD: 67 -> 123 (+56); 10.91% -> 18.33%
BAD: 547 -> 548 (+1)
where the affected warnings/projects are:
-Wanalyzer-malloc-leak:
GOOD: 0 -> 56 (+56); 0.00% -> 41.48%
BAD: 79
True positives: 0 -> 56 (+56)
(all in Doom)
-Wanalyzer-use-of-uninitialized-value:
GOOD: 0; 0.00%
BAD: 80 -> 81 (+1)
False positives:
pcre2-10.42: 0 -> 1 (+1)
gcc/analyzer/ChangeLog:
* kf.cc (class kf_sprintf): New.
(register_known_functions): Register it.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/doom-d_main-IdentifyVersion.c: New test.
* gcc.dg/analyzer/sprintf-1.c: New test.
* gcc.dg/analyzer/sprintf-concat.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/108968
* region-model.cc (region_model::get_rvalue_1): Handle VAR_DECLs
with a DECL_HARD_REGISTER by returning UNKNOWN.
gcc/testsuite/ChangeLog:
PR analyzer/108968
* gcc.dg/analyzer/uninit-pr108968-register.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Without this definition, the errno definition for newlib
isn't recognized as such, and these tests fail for newlib
targets:
FAIL: gcc.dg/analyzer/call-summaries-errno.c (test for warnings, line 16)
FAIL: gcc.dg/analyzer/call-summaries-errno.c (test for excess errors)
FAIL: gcc.dg/analyzer/errno-1.c (test for warnings, line 20)
FAIL: gcc.dg/analyzer/errno-1.c (test for excess errors)
FAIL: gcc.dg/analyzer/flex-without-call-summaries.c (test for excess errors)
FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 31)
FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 35)
FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 46)
FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 56)
FAIL: gcc.dg/analyzer/isatty-1.c (test for excess errors)
gcc/analyzer:
* kf.cc (register_known_functions): Add __errno function for newlib.
|
|
|
|
Previously, if the analyzer saw a call to a non-pure and non-const
built-in function that it didn't have explicit knowledge of the behavior
of, it would fall back to assuming that the builtin could have arbitrary
behavior, similar to a function defined outside of the current TU.
However, this only worked for BUILTIN_NORMAL functions that matched
gimple_builtin_call_types_compatible_p; for BUILT_IN_FRONTEND and
BUILT_IN_MD, and for mismatched types the analyzer would erroneously
assume that the builtin had no side-effects, leading e.g. to
PR analyzer/107565, where the analyzer falsely reported that x
was still uninitialized after this target-specific builtin:
_1 = __builtin_ia32_rdrand64_step (&x);
This patch generalizes the handling to cover all classes of builtin,
fixing the above false positive.
Unfortunately this patch regresses gcc.dg/analyzer/pr99716-1.c due to
the:
fprintf (fp, "hello");
being optimized to:
__builtin_fwrite ("hello", 1, (ssizetype)5, fp_6);
and the latter has gimple_builtin_call_types_compatible_p return false,
whereas the original call had it return true. I'm assuming that this is
an optimization bug, and have filed it as PR middle-end/108988. The
effect on the analyzer is that it fails to recognize the call to
__builtin_fwrite and instead assumes arbitraty side-effects (including
that it could call fclose on fp, hence the report about the leak goes
away).
I tried various more involved fixes with new heuristics for handling
built-ins that aren't explicitly covered by the analyzer, but those
fixes tended to introduce many more regressions, so I'm going with this
simpler fix.
gcc/analyzer/ChangeLog:
PR analyzer/107565
* region-model.cc (region_model::on_call_pre): Flatten logic by
returning early. Consolidate logic for detecting const and pure
functions. When considering whether an unhandled built-in
function has side-effects, consider all kinds of builtin, rather
than just BUILT_IN_NORMAL, and don't require
gimple_builtin_call_types_compatible_p.
gcc/testsuite/ChangeLog:
PR analyzer/107565
* gcc.dg/analyzer/builtins-pr107565.c: New test.
* gcc.dg/analyzer/pr99716-1.c (test_2): Mark the leak as xfailing.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/108935
* infinite-recursion.cc (contains_unknown_p): New.
(sufficiently_different_region_binding_p): New function, splitting
out inner loop from...
(sufficiently_different_p): ...here. Extend detection of unknown
svalues to also include svalues that contain unknown. Treat
changes in frames below the entry to the recursion as being
sufficiently different to reject being an infinite recursion.
gcc/testsuite/ChangeLog:
PR analyzer/108935
* gcc.dg/analyzer/infinite-recursion-pr108935-1.c: New test.
* gcc.dg/analyzer/infinite-recursion-pr108935-1a.c: New test.
* gcc.dg/analyzer/infinite-recursion-pr108935-2.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/108830 reports a situation in which there are lots of
followup -Wanalyzer-null-dereference warnings after the first access of
a NULL pointer, leading to very noisy output from -fanalyzer.
The analyzer's logic for stopping emitting multiple warnings from a
state machine doesn't quite work for NULL pointers: it attempts to
transition the malloc state machine's NULL pointer to the "stop" state,
which doesn't seem to make much sense in retrospect, and seems to get
confused over types.
Similarly, poisoned_value_diagnostic can be very noisy for uninit
variables, emitting a warning for every access to an uninitialized
variable. In theory, region_model::check_for_poison makes some attempts
to suppress followups, but only for the symbolic value itself; if the
user's code keeps accessing the same region, we would get a warning on
each one. For example, this showed up in Doom's s_sound.c where there
were 7 followup uninit warnings after the first uninit warning in
"S_ChangeMusic".
This patch adds an extra mechanism, giving pending diagnostics the
option of stopping the analysis of an execution path if they're saved
for emission on it, and turning this on for these warnings:
-Wanalyzer-null-dereference
-Wanalyzer-null-argument
-Wanalyzer-use-after-free
-Wanalyzer-use-of-pointer-in-stale-stack-frame
-Wanalyzer-use-of-uninitialized-value
Doing so should hopefully reduce the cascades of diagnostics that
-fanalyzer can sometimes emit.
I added a -fno-analyzer-suppress-followups for the cases where you
really want the followup warnings (e.g. in some DejaGnu tests, and
for microbenchmarks of UB detection, such as PR analyzer/104224).
Integration testing shows this patch reduces the number of probable
false positives reported by 94, and finds one more true positive:
Comparison: 9.34% -> 10.91%
GOOD: 66 -> 67 (+1)
BAD: 641 -> 547 (-94)
where the affected warnings/projects are:
-Wanalyzer-null-dereference: 0.00% GOOD: 0 BAD: 269 -> 239 (-30)
Unclassified: 257 -> 228 (-29)
apr-1.7.0: 12 -> 5 (-7)
doom: 1 -> 0 (-1)
haproxy-2.7.1: 47 -> 41 (-6)
ImageMagick-7.1.0-57: 13 -> 9 (-4)
qemu-7.2.0: 165 -> 154 (-11)
Known false: 7 -> 6 (-1)
xz-5.4.0: 4 -> 3 (-1)
-Wanalyzer-use-of-uninitialized-value: 0.00% GOOD: 0 BAD: 143 -> 80 (-63)
Known false: 47 -> 16 (-31)
doom: 42 -> 11 (-31)
Unclassified: 96 -> 64 (-32)
coreutils-9.1: 14 -> 10 (-4)
haproxy-2.7.1: 29 -> 23 (-6)
qemu-7.2.0: 48 -> 26 (-22)
-Wanalyzer-null-argument: 0.00% -> 2.33% GOOD: 0 -> 1 (+1) BAD: 43 -> 42 (-1)
Unclassified: 39 -> 38 (-1)
due to coreutils-9.1: 9 -> 8 (-1)
True positive: 0 -> 1 (+1)
(in haproxy-2.7.1)
gcc/analyzer/ChangeLog:
PR analyzer/108830
* analyzer.opt (fanalyzer-suppress-followups): New option.
* engine.cc (impl_region_model_context::warn): Terminate the path
if the diagnostic's terminate_path_p vfunc returns true and
-fanalyzer-suppress-followups is true (the default).
(impl_sm_context::warn): Likewise, for both overloads.
* pending-diagnostic.h (pending_diagnostic::terminate_path_p): New
vfunc.
* program-state.cc (program_state::on_edge): Terminate the path if
the ctxt requests it during updating the edge.
* region-model.cc (poisoned_value_diagnostic::terminate_path_p):
New vfunc.
* sm-malloc.cc (null_deref::terminate_path_p): New vfunc.
(null_arg::terminate_path_p): New vfunc.
gcc/ChangeLog:
PR analyzer/108830
* doc/invoke.texi: Document -fno-analyzer-suppress-followups.
gcc/testsuite/ChangeLog:
PR analyzer/108830
* gcc.dg/analyzer/attribute-nonnull.c: Update for
-Wanalyzer-use-of-uninitialized-value terminating analysis along
a path.
* gcc.dg/analyzer/call-summaries-2.c: Likewise.
* gcc.dg/analyzer/data-model-1.c: Likewise.
* gcc.dg/analyzer/data-model-5.c: Likewise.
* gcc.dg/analyzer/doom-s_sound-pr108867.c: New test.
* gcc.dg/analyzer/memset-CVE-2017-18549-1.c: Add
-fno-analyzer-suppress-followups.
* gcc.dg/analyzer/null-deref-pr108830.c: New test.
* gcc.dg/analyzer/pipe-1.c: Add -fno-analyzer-suppress-followups.
* gcc.dg/analyzer/pipe-void-return.c: Likewise.
* gcc.dg/analyzer/pipe2-1.c: Likewise.
* gcc.dg/analyzer/pr101547.c: Update for
-Wanalyzer-use-of-uninitialized-value terminating analysis along
a path.
* gcc.dg/analyzer/pr101875.c: Likewise.
* gcc.dg/analyzer/pr104224-split.c: New test, based on...
* gcc.dg/analyzer/pr104224.c: Add
-fno-analyzer-suppress-followups.
* gcc.dg/analyzer/realloc-2.c: Add
-fno-analyzer-suppress-followups.
* gcc.dg/analyzer/realloc-3.c: Likewise.
* gcc.dg/analyzer/realloc-5.c: Likewise.
* gcc.dg/analyzer/stdarg-1-ms_abi.c: Likewise.
* gcc.dg/analyzer/stdarg-1-sysv_abi.c: Likewise.
* gcc.dg/analyzer/stdarg-1.c: Likewise.
* gcc.dg/analyzer/symbolic-1.c: Likewise.
* gcc.dg/analyzer/symbolic-7.c: Update for
-Wanalyzer-use-of-uninitialized-value terminating analysis along a
path.
* gcc.dg/analyzer/uninit-4.c: Likewise.
* gcc.dg/analyzer/uninit-8.c: New test.
* gcc.dg/analyzer/uninit-pr94713.c: Update for
-Wanalyzer-use-of-uninitialized-value terminating analysis along a
path.
* gcc.dg/analyzer/zlib-6a.c: Add -fno-analyzer-suppress-followups.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/108806 reports false +ves seen from -fanalyzer on code like this
in qemu-7.2.0's hw/intc/omap_intc.c:
[...snip...]
struct omap_intr_handler_bank_s* bank = NULL;
if ((offset & 0xf80) == 0x80) {
[...set "bank" to non-NULL...]
}
switch (offset) {
[...snip various cases that don't deref "bank"...]
case 0x80:
return bank->inputs;
case 0x84:
return bank->mask;
[...etc...]
}
where the analyzer falsely complains about execution paths in which
"(offset & 0xf80) == 0x80" was false (leaving "bank" as NULL), but then
in which "switch (offset)" goes to a case for which
"(offset & 0xf80) == 0x80" is true and dereferences NULL "bank", i.e.
paths in which "(offset & 0xf80) == 0x80" is both true *and* false.
This patch adds enough logic to constraint_manager for -fanalyzer to
reject such execution paths as impossible, fixing the false +ves.
Integration testing shows this eliminates 20 probable false positives:
Comparison: 9.08% -> 9.34% GOOD: 66 BAD: 661 -> 641 (-20)
where the affected warnings/projects are:
-Wanalyzer-null-dereference: 0.00% GOOD: 0 BAD: 279 -> 269 (-10)
qemu-7.2.0: 175 -> 165 (-10)
-Wanalyzer-use-of-uninitialized-value: 0.00% GOOD: 0 BAD: 153 -> 143 (-10)
coreutils-9.1: 18 -> 14 (-4)
qemu-7.2.0: 54 -> 48 (-6)
gcc/analyzer/ChangeLog:
PR analyzer/108806
* constraint-manager.cc (bounded_range::dump_to_pp): Use
bounded_range::singleton_p.
(constraint_manager::add_bounded_ranges): Handle singleton ranges
by adding an EQ_EXPR constraint.
(constraint_manager::impossible_derived_conditions_p): New.
(constraint_manager::eval_condition): Reject EQ_EXPR when it would
imply impossible derived conditions.
(selftest::test_bits): New.
(selftest::run_constraint_manager_tests): Run it.
* constraint-manager.h (bounded_range::singleton_p): New.
(constraint_manager::impossible_derived_conditions_p): New decl.
* region-model.cc (region_model::get_rvalue_1): Handle
BIT_AND_EXPR, BIT_IOR_EXPR, and BIT_XOR_EXPR.
gcc/testsuite/ChangeLog:
PR analyzer/108806
* gcc.dg/analyzer/null-deref-pr108806-qemu.c: New test.
* gcc.dg/analyzer/pr103217.c: Add -Wno-analyzer-too-complex.
* gcc.dg/analyzer/switch.c (test_bitmask_1): New.
(test_bitmask_2): New.
* gcc.dg/analyzer/uninit-pr108806-qemu.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
This patch updates poisoned_value_diagnostic so that, where possible,
it checks to see if the value is still poisoned along the execution
path seen during feasibility analysis, rather than just that seen
in the exploded graph.
Integration testing shows this reduction in the number of
false positives:
-Wanalyzer-use-of-uninitialized-value: 191 -> 153 (-38)
where the changes happen in:
coreutils-9.1: 34 -> 20 (-14)
qemu-7.2.0: 78 -> 54 (-24)
gcc/analyzer/ChangeLog:
PR analyzer/108664
PR analyzer/108666
PR analyzer/108725
* diagnostic-manager.cc (epath_finder::get_best_epath): Add
"target_stmt" param.
(epath_finder::explore_feasible_paths): Likewise.
(epath_finder::process_worklist_item): Likewise.
(saved_diagnostic::calc_best_epath): Pass m_stmt to
epath_finder::get_best_epath.
* engine.cc (feasibility_state::maybe_update_for_edge): Move
per-stmt logic to...
(feasibility_state::update_for_stmt): ...this new function.
* exploded-graph.h (feasibility_state::update_for_stmt): New decl.
* feasible-graph.cc (feasible_node::get_state_at_stmt): New.
* feasible-graph.h: Include "analyzer/exploded-graph.h".
(feasible_node::get_state_at_stmt): New decl.
* infinite-recursion.cc
(infinite_recursion_diagnostic::check_valid_fpath_p): Update for
vfunc signature change.
* pending-diagnostic.h (pending_diagnostic::check_valid_fpath_p):
Convert first param to a reference. Add stmt param.
* region-model.cc: Include "analyzer/feasible-graph.h".
(poisoned_value_diagnostic::poisoned_value_diagnostic): Add
"check_expr" param.
(poisoned_value_diagnostic::check_valid_fpath_p): New.
(poisoned_value_diagnostic::m_check_expr): New field.
(region_model::check_for_poison): Attempt to supply a check_expr
to the diagnostic
(region_model::deref_rvalue): Add NULL for new check_expr param
of poisoned_value_diagnostic.
(region_model::get_or_create_region_for_heap_alloc): Don't reuse
regions that are marked as TOUCHED.
gcc/testsuite/ChangeLog:
PR analyzer/108664
PR analyzer/108666
PR analyzer/108725
* gcc.dg/analyzer/coreutils-cksum-pr108664.c: New test.
* gcc.dg/analyzer/coreutils-sum-pr108666.c: New test.
* gcc.dg/analyzer/torture/uninit-pr108725.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
Integration testing shows this patch fixes all 9 known false positives
from -Wanalyzer-deref-before-check within ImageMagick-7.1.0-57, and
eliminates 34 further as-yet unassessed such diagnostics, without
eliminating the 1 known true positive.
This improves the rate of true positives for the warning from
1.56% to 4.76% of the total:
-Wanalyzer-deref-before-check: 1.56% -> 4.76% (GOOD: 1 BAD: 63->20)
TRUE: 1
FALSE: 15 -> 6 (-9)
ImageMagick-7.1.0-57: 9 -> 0 (-9)
TODO: 48 -> 14 (-34)
ImageMagick-7.1.0-57: 21 -> 1 (-20)
qemu-7.2.0: 25 -> 11 (-14)
gcc/analyzer/ChangeLog:
PR analyzer/108745
* sm-malloc.cc (deref_before_check::emit): Reject the warning if
the check occurs within a macro defintion.
gcc/testsuite/ChangeLog:
PR analyzer/108745
* gcc.dg/analyzer/deref-before-check-macro-pr108745.c: New test.
* gcc.dg/analyzer/deref-before-check-macro.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/108733 reports various false positives in qemu from
-Wanalyzer-use-of-uninitialized-value with __attribute__((cleanup))
at -O1 and above.
Root cause is that the state-purging code was failing to treat:
_25 = MEM[(void * *)&val];
as a usage of "val", leading to it erroneously purging the
initialization of "val" along an execution path that didn't otherwise
use "val", apart from the __attribute__((cleanup)).
Fixed thusly.
Integration testing on the patch show this change in the number of
diagnostics:
-Wanalyzer-use-of-uninitialized-value
coreutils-9.1: 18 -> 16 (-2)
qemu-7.2.0: 87 -> 80 (-7)
where all that I investigated appear to have been false positives, hence
an improvement.
gcc/analyzer/ChangeLog:
PR analyzer/108733
* state-purge.cc (get_candidate_for_purging): Add ADDR_EXPR
and MEM_REF.
gcc/testsuite/ChangeLog:
PR analyzer/108733
* gcc.dg/analyzer/torture/uninit-pr108733.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/108704 reports many false positives seen from
-Wanalyzer-use-of-uninitialized-value on qemu's softfloat.c on code like
the following:
struct st s;
s = foo ();
s = bar (s); // bogusly reports that s is uninitialized here
where e.g. "struct st" is "floatx80" in the qemu examples.
The root cause is overzealous purging of on-stack structs in the code I
added in r12-7718-gfaacafd2306ad7, where at:
s = bar (s);
state_purge_per_decl::process_point_backwards "sees" the assignment to 's'
and stops processing, effectively treating 's' as unneeded before this
stmt, not noticing the use of 's' in the argument.
Fixed thusly.
The patch greatly reduces the number of
-Wanalyzer-use-of-uninitialized-value warnings from my integration tests:
ImageMagick-7.1.0-57: 10 -> 6 (-4)
qemu-7.2: 858 -> 87 (-771)
haproxy-2.7.1: 1 -> 0 (-1)
All of the above that I've examined appear to be false positives.
gcc/analyzer/ChangeLog:
PR analyzer/108704
* state-purge.cc (state_purge_per_decl::process_point_backwards):
Don't stop processing the decl if it's fully overwritten by
this stmt if it's also used by this stmt.
gcc/testsuite/ChangeLog:
PR analyzer/108704
* gcc.dg/analyzer/uninit-7.c: New test.
* gcc.dg/analyzer/uninit-pr108704.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
[PR108661]
My integration testing shows many false positives from
-Wanalyzer-use-of-uninitialized-value.
One cause turns out to be that as of r13-1404-g97baacba963c06
fd_state_machine::on_stmt recognizes calls to "read", and returns true,
so that region_model::on_call_post doesn't call handle_unrecognized_call
on them, and so the analyzer erroneously "thinks" that the buffer
pointed to by "read" is never touched by the "read" call.
This works for "fread" because sm-file.cc implements kf_fread, which
handles calls to "fread" by clobbering the buffer pointed to. In the
long term we should probably be smarter about this and bifurcate the
analysis to consider e.g. errors vs full reads vs partial reads, etc
(which I'm tracking in PR analyzer/108689).
In the meantime, this patch adds a kf_read for "read" analogous to the
one for "fread", fixing 6 false positives seen in git-2.39.0 and
2 in haproxy-2.7.1.
gcc/analyzer/ChangeLog:
PR analyzer/108661
* sm-fd.cc (class kf_read): New.
(register_known_fd_functions): Register "read".
* sm-file.cc (class kf_fread): Update comment.
gcc/testsuite/ChangeLog:
PR analyzer/108661
* gcc.dg/analyzer/fread-pr108661.c: New test.
* gcc.dg/analyzer/read-pr108661.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/108633
* sm-fd.cc (fd_state_machine::check_for_fd_attrs): Add missing
"continue".
(fd_state_machine::on_listen): Don't issue phase-mismatch or
type-mismatch warnings for the "invalid" state.
gcc/testsuite/ChangeLog:
PR analyzer/108633
* gcc.dg/analyzer/fd-pr108633.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/108616
* pending-diagnostic.cc (fixup_location_in_macro_p): Add "alloca"
to macros that we shouldn't unwind inside.
gcc/testsuite/ChangeLog:
PR analyzer/108616
* gcc.dg/analyzer/allocation-size-multiline-3.c: New test.
* gcc.dg/analyzer/test-alloca.h: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
Reject -Wanalyzer-infinite-recursion diagnostics in which control flow
has been affected by conjured_svalues between the initial call to a
function and the subsequent entry to that function. This prevents false
positives such as in qemu's recursive JSON parser where function calls are
changing state in the rest of the program (e.g. consuming tokens), despite
the modelled state being effectively identical at both nested entrypoints.
gcc/analyzer/ChangeLog:
PR analyzer/108524
* analyzer.h (class feasible_node): New forward decl.
* diagnostic-manager.cc (epath_finder::get_best_epath): Add "pd"
param.
(epath_finder::explore_feasible_paths): Likewise.
(epath_finder::process_worklist_item): Likewise. Use it to call
pending_diagnostic::check_valid_fpath_p on the final fpath to
give pending_diagnostic a way to add additional restrictions on
feasibility.
(saved_diagnostic::calc_best_epath): Pass pending_diagnostic to
epath_finder::get_best_epath.
* infinite-recursion.cc: Include "analyzer/feasible-graph.h".
(infinite_recursion_diagnostic::check_valid_fpath_p): New.
(infinite_recursion_diagnostic::fedge_uses_conjured_svalue_p): New.
(infinite_recursion_diagnostic::expr_uses_conjured_svalue_p): New.
* pending-diagnostic.h (pending_diagnostic::check_valid_fpath_p):
New vfunc.
gcc/testsuite/ChangeLog:
PR analyzer/108524
* gcc.dg/analyzer/infinite-recursion-pr108524-1.c: New test.
* gcc.dg/analyzer/infinite-recursion-pr108524-2.c: New test.
* gcc.dg/analyzer/infinite-recursion-pr108524-qobject-json-parser.c:
New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
My integration testing [1] of -fanalyzer in GCC 13 is showing a lot of
diagnostics from the new -Wanalyzer-deref-before-check warning on
real-world C projects, and most of these seem to be false positives.
This patch updates the warning to make it much less likely to fire:
- only intraprocedural cases are now reported
- reject cases in which there are control flow paths to the check
that didn't come through the dereference, by looking at BB dominator
information. This fixes a false positive seen in git-2.39.0's
pack-revindex.c: load_revindex_from_disk (PR analyzer/108455), in
which a shared "cleanup:" section checks "data" for NULL, and
depending on how much of the function is executed "data" might or
might not have already been dereferenced.
The counts of -Wanalyzer-deref-before-check diagnostics in [1]
before/after this patch show this improvement:
Known false positives: 6 -> 0 (-6)
Known true positives: 1 -> 1
Unclassified positives: 123 -> 63 (-60)
[1] https://github.com/davidmalcolm/gcc-analyzer-integration-tests
gcc/analyzer/ChangeLog:
PR analyzer/108455
* analyzer.h (class checker_event): New forward decl.
(class state_change_event): Indent.
(class warning_event): New forward decl.
* checker-event.cc (state_change_event::state_change_event): Add
"enode" param.
(warning_event::get_desc): Update for new param of
evdesc::final_event ctor.
* checker-event.h (state_change_event::state_change_event): Add
"enode" param.
(state_change_event::get_exploded_node): New accessor.
(state_change_event::m_enode): New field.
(warning_event::warning_event): New "enode" param.
(warning_event::get_exploded_node): New accessor.
(warning_event::m_enode): New field.
* diagnostic-manager.cc
(state_change_event_creator::on_global_state_change): Pass
src_node to state_change_event ctor.
(state_change_event_creator::on_state_change): Likewise.
(null_assignment_sm_context::set_next_state): Pass NULL for
new param of state_change_event ctor.
* infinite-recursion.cc
(infinite_recursion_diagnostic::add_final_event): Update for new
param of warning_event ctor.
* pending-diagnostic.cc (pending_diagnostic::add_final_event):
Pass enode to warning_event ctor.
* pending-diagnostic.h (evdesc::final_event): Add reference to
warning_event.
* sm-malloc.cc: Include "analyzer/checker-event.h" and
"analyzer/exploded-graph.h".
(deref_before_check::deref_before_check): Initialize new fields.
(deref_before_check::emit): Reject warnings in which we were
unable to determine the enodes of the dereference and the check.
Reject warnings interprocedural warnings. Reject warnings in which
the dereference doesn't dominate the check.
(deref_before_check::describe_state_change): Set m_deref_enode.
(deref_before_check::describe_final_event): Set m_check_enode.
(deref_before_check::m_deref_enode): New field.
(deref_before_check::m_check_enode): New field.
gcc/testsuite/ChangeLog:
PR analyzer/108455
* gcc.dg/analyzer/deref-before-check-1.c: Add test coverage
involving dominance.
* gcc.dg/analyzer/deref-before-check-pr108455-1.c: New test.
* gcc.dg/analyzer/deref-before-check-pr108455-git-pack-revindex.c:
New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
|
|
Assume that switch on an enum doesn't follow an implicit default
skipping all cases when all enum values are covered by cases.
Fixes various false positives from -Wanalyzer-use-of-uninitialized-value
such as this one seen in Doom:
p_maputl.c: In function 'P_BoxOnLineSide':
p_maputl.c:151:8: warning: use of uninitialized value 'p1' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
151 | if (p1 == p2)
| ^
'P_BoxOnLineSide': events 1-5
|
| 115 | int p1;
| | ^~
| | |
| | (1) region created on stack here
| | (2) capacity: 4 bytes
|......
| 118 | switch (ld->slopetype)
| | ~~~~~~
| | |
| | (3) following 'default:' branch...
|......
| 151 | if (p1 == p2)
| | ~
| | |
| | (4) ...to here
| | (5) use of uninitialized value 'p1' here
|
where "ld->slopetype" is a "slopetype_t" enum, and for every value of
that enum the switch has a case that initializes "p1".
gcc/analyzer/ChangeLog:
PR analyzer/105273
* region-model.cc (has_nondefault_case_for_value_p): New.
(has_nondefault_cases_for_all_enum_values_p): New.
(region_model::apply_constraints_for_gswitch): Skip
implicitly-created "default" when switching on an enum
and all enum values have non-default cases.
(rejected_default_case::dump_to_pp): New.
* region-model.h (region_model_context::possibly_tainted_p): New
decl.
(class rejected_default_case): New.
* sm-taint.cc (region_model_context::possibly_tainted_p): New.
* supergraph.cc (switch_cfg_superedge::dump_label_to_pp): Dump
when implicitly_created_default_p.
(switch_cfg_superedge::implicitly_created_default_p): New.
* supergraph.h
(switch_cfg_superedge::implicitly_created_default_p): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/105273
* gcc.dg/analyzer/switch-enum-1.c: New test.
* gcc.dg/analyzer/switch-enum-2.c: New test.
* gcc.dg/analyzer/switch-enum-pr105273-git-vreportf-2.c: New test.
* gcc.dg/analyzer/switch-enum-taint-1.c: New test.
* gcc.dg/analyzer/switch-wrong-enum.c: New test.
* gcc.dg/analyzer/torture/switch-enum-pr105273-doom-p_floor.c: New
test.
* gcc.dg/analyzer/torture/switch-enum-pr105273-doom-p_maputl.c:
New test.
* gcc.dg/analyzer/torture/switch-enum-pr105273-git-vreportf-1.c:
New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
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>
|
|
2022 -> 2023
|
|
|
|
PR analyzer/106479 notes that we don't always show the region-creation
event for a memmove from an uninitialized stack region. This occurs
when using kf_memcpy_memmove. Fix by passing a src_region hint to
region_model::check_for_poison.
gcc/analyzer/ChangeLog:
PR analyzer/106479
* kf.cc (kf_memcpy_memmove::impl_call_pre): Pass in source region
to region_model::check_for_poison.
* region-model-asm.cc (region_model::on_asm_stmt): Pass NULL
region to region_model::check_for_poison.
* region-model.cc (region_model::check_for_poison): Add
"src_region" param, and pass it to poisoned_value_diagnostic.
(region_model::on_assignment): Pass NULL region to
region_model::check_for_poison.
(region_model::get_rvalue): Likewise.
* region-model.h (region_model::check_for_poison): Add
"src_region" param.
* sm-fd.cc (fd_state_machine::on_accept): Pass in source region
to region_model::check_for_poison.
* varargs.cc (kf_va_copy::impl_call_pre): Pass NULL region to
region_model::check_for_poison.
(kf_va_arg::impl_call_pre): Pass in source region to
region_model::check_for_poison.
gcc/testsuite/ChangeLog:
PR analyzer/106479
* gcc.dg/analyzer/pr104308.c (test_memmove_within_uninit): Remove
xfail on region creation event.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/108065
* region.cc (decl_region::get_svalue_for_initializer): Bail out to
avoid calling binding_key::make with an empty region.
* store.cc (binding_map::apply_ctor_val_to_range): Likewise.
(binding_map::apply_ctor_pair_to_child_region): Likewise.
(binding_cluster::bind): Likewise.
(binding_cluster::purge_region): Likewise.
(binding_cluster::maybe_get_compound_binding): Likewise.
(binding_cluster::maybe_get_simple_value): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/108065
* gfortran.dg/analyzer/pr108065.f90: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/ChangeLog:
* Makefile.in (ANALYZER_OBJS): Update for renaming of
analyzer/region-model-impl-calls.cc to analyzer/kf.cc.
gcc/analyzer/ChangeLog:
* analyzer.h (class known_function): Expand comment.
* region-model-impl-calls.cc: Rename to...
* kf.cc: ...this.
* known-function-manager.h (class known_function_manager): Add
leading comment.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
[PR108003]
gcc/analyzer/ChangeLog:
PR analyzer/108003
* call-summary.cc
(call_summary_replay::convert_region_from_summary_1): Convert
heap_regs_in_use from auto_sbitmap to auto_bitmap.
* region-model-manager.cc
(region_model_manager::get_or_create_region_for_heap_alloc):
Convert from sbitmap to bitmap.
* region-model-manager.h: Likewise.
* region-model.cc
(region_model::get_or_create_region_for_heap_alloc): Convert from
auto_sbitmap to auto_bitmap.
(region_model::get_referenced_base_regions): Likewise.
* region-model.h: Include "bitmap.h" rather than "sbitmap.h".
(region_model::get_referenced_base_regions): Convert from
auto_sbitmap to auto_bitmap.
gcc/testsuite/ChangeLog:
PR analyzer/108003
* g++.dg/analyzer/pr108003.C: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|