Age | Commit message (Collapse) | Author | Files | Lines |
|
PR analyzer/105264 reports that the analyzer can fail to treat
(PTR + IDX) and PTR[IDX] as referring to the same memory under
some situations.
There are various ways in which this can happen when IDX is a
symbolic value, due to having several ways in which such memory
regions can be referred to symbolically. I attempted to fix this by
being smarter when folding svalues and regions, but this fix
seems too fiddly to attempt in stage 4.
Instead, this less ambitious patch fixes a false positive from
-Wanalyzer-use-of-uninitialized-value by making the analyzer's escape
analysis smarter, so that it treats *PTR as escaping when
(PTR + OFFSET) is passed to an external function, and thus
it treats *PTR as possibly-initialized (the "passing &PTR[IDX]" case
was already working).
gcc/analyzer/ChangeLog:
PR analyzer/105264
* region-model-reachability.cc (reachable_regions::handle_parm):
Use maybe_get_deref_base_region rather than just region_svalue, to
handle pointer arithmetic also.
* svalue.cc (svalue::maybe_get_deref_base_region): New.
* svalue.h (svalue::maybe_get_deref_base_region): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/105264
* gcc.dg/analyzer/torture/symbolic-10.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/105252
* svalue.cc (cmp_cst): When comparing VECTOR_CSTs, compare the
types of the encoded elements before calling cmp_cst on them.
gcc/testsuite/ChangeLog:
PR analyzer/105252
* gcc.dg/analyzer/pr105252.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/103892 reports a false positive from -Wanalyzer-double-free.
The root cause is the analyzer failing to properly handle "unknown"
symbolic regions, and thus confusing two different expressions.
Specifically, the analyzer eventually hits the complexity limit for
symbolic values, and starts using an "unknown" svalue for a pointer.
The analyzer uses
symbolic_region(unknown_svalue([of ptr type]))
i.e.
(*UNKNOWN_PTR)
in a few places to mean "we have an lvalue, but we're not going to
attempt to track what it is anymore".
"Unknown" should probably be renamed to "unknowable"; in theory, any
operation on such an unknown svalue should be also an unknown svalue.
The issue is that in various places where we create child regions, we
were failing to check for the parent region being (*UNKNOWN_PTR), and so
were erroneously creating regions based on (*UNKNOWN_PTR), such as
*(UNKNOWN_PTR + OFFSET). The state-machine handling was erroneously
allowing e.g. INITIAL_VALUE (*(UNKNOWN_PTR + OFFSET)) to have state,
and thus we could record that such a value had had "free" called on it,
and thus eventually false report a double-free when a different
expression incorrectly "simplified" to the same expression.
This patch fixes things by checking when creating the various kinds of
child region for (*UNKNOWN_PTR) as the parent region, and simply
returning another (*UNKNOWN_PTR) for such child regions (using the
appropriate type).
Doing so fixes the false positive, and also fixes a state explosion on
this testcase, as the states at the program points more rapidly reach
a fixed point where everything is unknown. I checked for other cases
that no longer needed -Wno-analyzer-too-complex; the only other one
seems to be gcc.dg/analyzer/pr96841.c, but that seems to already have
become redundant at some point before this patch.
gcc/analyzer/ChangeLog:
PR analyzer/103892
* region-model-manager.cc
(region_model_manager::get_unknown_symbolic_region): New,
extracted from...
(region_model_manager::get_field_region): ...here.
(region_model_manager::get_element_region): Use it here.
(region_model_manager::get_offset_region): Likewise.
(region_model_manager::get_sized_region): Likewise.
(region_model_manager::get_cast_region): Likewise.
(region_model_manager::get_bit_range): Likewise.
* region-model.h
(region_model_manager::get_unknown_symbolic_region): New decl.
* region.cc (symbolic_region::symbolic_region): Handle sval_ptr
having NULL type.
(symbolic_region::dump_to_pp): Handle having NULL type.
gcc/testsuite/ChangeLog:
PR analyzer/103892
* gcc.dg/analyzer/pr103892.c: New test.
* gcc.dg/analyzer/pr96841.c: Drop redundant
-Wno-analyzer-too-complex.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/102208 reports false positives from -Wanalyzer-malloc-leak.
The root cause is the analyzer getting confused about symbolic writes
that could alias a pointer referencing a malloced buffer.
struct st
{
void *ptr;
int arr[10];
};
struct st test (int idx)
{
struct st s;
s.ptr = __builtin_malloc (1024); /* (1) */
s.arr[idx] = 42; /* (2) */
return s;
}
When removing overlapping bindings at (2),
store::remove_overlapping_bindings was failing to pass on the
uncertainty_t *, and thus when clobbering the binding of s.ptr, the
heap-allocated pointer was not being added to the set of maybe-bound
svalues, and thus being treated as leaking.
This patch fixes this, so that s.ptr from (1) is treated as maybe-bound
after the write at (2), fixing the leak false postive.
Doing so requires the store to be smarter about how clobbering happens
with various combinations of concrete keys and symbolic keys within
concrete clusters and symbolic clusters, so that we don't lose warnings
about definite leaks.
gcc/analyzer/ChangeLog:
PR analyzer/102208
* store.cc (binding_map::remove_overlapping_bindings): Add
"always_overlap" param, using it to generalize to the case where
we want to remove all bindings. Update "uncertainty" logic to
only record maybe-bound values for cases where there is a symbolic
write involved.
(binding_cluster::mark_region_as_unknown): Split param "reg" into
"reg_to_bind" and "reg_for_overlap".
(binding_cluster::maybe_get_compound_binding): Pass "false" to
binding_map::remove_overlapping_bindings new "always_overlap" param.
(binding_cluster::remove_overlapping_bindings): Determine
"always_overlap" and pass it to
binding_map::remove_overlapping_bindings.
(store::set_value): Pass uncertainty to remove_overlapping_bindings
call. Update for new param of
binding_cluster::mark_region_as_unknown, passing both the base
region of the iter_cluster, and the lhs_reg.
(store::mark_region_as_unknown): Update for new param of
binding_cluster::mark_region_as_unknown, passing "reg" for both.
(store::remove_overlapping_bindings): Add param "uncertainty", and
pass it on to call to
binding_cluster::remove_overlapping_bindings.
* store.h (binding_map::remove_overlapping_bindings): Add
"always_overlap" param.
(binding_cluster::mark_region_as_unknown): Split param "reg" into
"reg_to_bind" and "reg_for_overlap".
(store::remove_overlapping_bindings): Add param "uncertainty".
gcc/testsuite/ChangeLog:
PR analyzer/102208
* gcc.dg/analyzer/symbolic-9.c: New test.
* gcc.dg/analyzer/torture/leak-pr102308-1.c: New test.
* gcc.dg/analyzer/torture/leak-pr102308-2.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
In r12-7809-g5f6197d7c197f9 I added -fdump-analyzer-untracked as support
for DejaGnu testing of an optimization of -fanalyzer,
PR analyzer/104954.
PR testsuite/105085 notes testsuite failures of the form:
FAIL: gcc.dg/analyzer/untracked-1.c (test for excess errors)
Excess errors:
cc1: warning: track '*.LC1': yes
where these warnings are emitted on some targets where the test
causes labelled constants to be created in the constant pool.
We probably ought not to be tracking the values of such decls in the
store, given that they're meant to be constant, and I attempted various
fixes to make the "should we track this decl" logic smarter, but given
that we're in stage 4, the simplest fix seems to be for
-fdump-analyzer-untracked to skip such decls in its output, to minimize
test output differences between targets.
gcc/analyzer/ChangeLog:
PR testsuite/105085
* region-model-manager.cc (dump_untracked_region): Skip decls in
the constant pool.
gcc/testsuite/ChangeLog:
PR testsuite/105085
* gcc.dg/analyzer/untracked-1.c: Add further test coverage.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
PR analyzer/105087 describes a false positive from
-Wanalyzer-double-free in which the analyzer erroneously considers two
successive inlined vasprintf calls to have allocated the same pointer.
The root cause is that the result written back from vasprintf is a
conjured_svalue, and that we normally purge state when reusing a
conjured_svalue, but various places in the code were calling
region_model_manager::get_or_create_conjured_svalue but failing to
then call region_model::purge_state_involving on the result.
This patch fixes things by moving responsibility for calling
region_model::purge_state_involving into
region_model_manager::get_or_create_conjured_svalue, so that it is
always called when reusing a conjured_svalue, fixing the false positive.
gcc/analyzer/ChangeLog:
PR analyzer/105087
* analyzer.h (class conjured_purge): New forward decl.
* region-model-asm.cc (region_model::on_asm_stmt): Add
conjured_purge param to calls binding_cluster::on_asm and
region_model_manager::get_or_create_conjured_svalue.
* region-model-impl-calls.cc
(call_details::get_or_create_conjured_svalue): Likewise for call
to region_model_manager::get_or_create_conjured_svalue.
(region_model::impl_call_fgets): Remove call to
region_model::purge_state_involving, as this is now done
implicitly by call_details::get_or_create_conjured_svalue.
(region_model::impl_call_fread): Likewise.
(region_model::impl_call_strchr): Pass conjured_purge param to
call to region_model_manager::get_or_create_conjured_svalue.
* region-model-manager.cc (conjured_purge::purge): New.
(region_model_manager::get_or_create_conjured_svalue): Add
param "p". Use it to purge state when reusing an existing
conjured_svalue.
* region-model.cc (region_model::on_call_pre): Replace call to
region_model::purge_state_involving with passing conjured_purge
to region_model_manager::get_or_create_conjured_svalue.
(region_model::handle_unrecognized_call): Pass conjured_purge to
store::on_unknown_fncall.
* region-model.h
(region_model_manager::get_or_create_conjured_svalue): Add param
"p".
* store.cc (binding_cluster::on_unknown_fncall): Likewise. Pass
it on to region_model_manager::get_or_create_conjured_svalue.
(binding_cluster::on_asm): Likewise.
(store::on_unknown_fncall): Add param "p" and pass it on to
binding_cluster::on_unknown_fncall.
* store.h (binding_cluster::on_unknown_fncall): Add param p.
(binding_cluster::on_asm): Likewise.
(store::on_unknown_fncall): Likewise.
* svalue.h (class conjured_purge): New.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/pr105087-1.c: New test.
* gcc.dg/analyzer/pr105087-2.c: New test.
* gcc.dg/analyzer/vasprintf-1.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/105074
* region.cc (ipa_ref_requires_tracking): Drop "context_fndecl",
instead using the ref->referring to get the cgraph node of the
caller.
(symnode_requires_tracking_p): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/105074
* gcc.dg/analyzer/pr105074.c: New test.
* gcc.dg/analyzer/untracked-1.c (extern_fn_char_ptr): New decl.
(test_13): New.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
In r12-7809-g5f6197d7c197f9d2b7fb2e1a19dac39a023755e8 I added an
optimization to avoid tracking the state of certain memory regions
in the store.
Unfortunately, I didn't cover every way in which
store::get_or_create_cluster can be called for a base region, leading
to assertion failure ICEs in -fanalyzer on certain function calls
with certain params.
I've worked through all uses of store::get_or_create_cluster and found
four places where the assertion could fire.
This patch fixes them, and adds regression tests where possible.
gcc/analyzer/ChangeLog:
PR analyzer/105057
* store.cc (binding_cluster::make_unknown_relative_to): Reject
attempts to create a cluster for untracked base regions.
(store::set_value): Likewise.
(store::fill_region): Likewise.
(store::mark_region_as_unknown): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/105057
* gcc.dg/analyzer/fread-2.c: New test, as a regression test for
ICE in store::set_value on untracked base region.
* gcc.dg/analyzer/memset-2.c: Likewise, for ICE in
store::fill_region.
* gcc.dg/analyzer/strcpy-2.c: Likewise, for ICE in
store::mark_region_as_unknown.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/104954 tracks that -fanalyzer was taking a very long time
on a particular source file in the Linux kernel:
drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
One issue occurs with the repeated use of dynamic debug lines e.g. via
the DC_LOG_BANDWIDTH_CALCS macro, such as in print_bw_calcs_dceip in
drivers/gpu/drm/amd/display/dc/calcs/calcs_logger.h:
DC_LOG_BANDWIDTH_CALCS("#####################################################################");
DC_LOG_BANDWIDTH_CALCS("struct bw_calcs_dceip");
DC_LOG_BANDWIDTH_CALCS("#####################################################################");
[...snip dozens of lines...]
DC_LOG_BANDWIDTH_CALCS("[bw_fixed] dmif_request_buffer_size: %d",
bw_fixed_to_int(dceip->dmif_request_buffer_size));
When this is configured to use __dynamic_pr_debug, each of these becomes
code like:
do {
static struct _ddebug __attribute__((__aligned__(8)))
__attribute__((__section__("__dyndbg"))) __UNIQUE_ID_ddebug277 = {
[...snip...]
};
if (arch_static_branch(&__UNIQUE_ID_ddebug277.key, false))
__dynamic_pr_debug(&__UNIQUE_ID_ddebug277, [...the message...]);
} while (0);
The analyzer was naively seeing each call to __dynamic_pr_debug, noting
that the __UNIQUE_ID_nnnn object escapes. At each call, as successive
__UNIQUE_ID_nnnn object escapes, there are N escaped objects, and thus N
need clobbering, and so we have O(N^2) clobbering of escaped objects overall,
leading to huge amounts of pointless work: print_bw_calcs_data has 225
uses of DC_LOG_BANDWIDTH_CALCS, many of which are in loops.
This patch adds a way to identify declarations that aren't interesting
to the analyzer, so that we don't attempt to create binding_clusters
for them (i.e. we don't store any state for them in our state objects).
This is implemented by adding a new region::tracked_p, implemented for
declarations by walking the existing IPA data the first time the
analyzer sees a declaration, setting it to false for global vars that
have no loads/stores/aliases, and "sufficiently safe" address-of
ipa-refs.
The patch gives a large speedup of -fanalyzer on the above kernel
source file:
Before After
Total cc1 wallclock time: 180s 36s
analyzer wallclock time: 162s 17s
% spent in analyzer: 90% 47%
gcc/analyzer/ChangeLog:
PR analyzer/104954
* analyzer.opt (-fdump-analyzer-untracked): New option.
* engine.cc (impl_run_checkers): Handle it.
* region-model-asm.cc (region_model::on_asm_stmt): Don't attempt
to clobber regions with !tracked_p ().
* region-model-manager.cc (dump_untracked_region): New.
(region_model_manager::dump_untracked_regions): New.
(frame_region::dump_untracked_regions): New.
* region-model.h (region_model_manager::dump_untracked_regions):
New decl.
* region.cc (ipa_ref_requires_tracking): New.
(symnode_requires_tracking_p): New.
(decl_region::calc_tracked_p): New.
* region.h (region::tracked_p): New vfunc.
(frame_region::dump_untracked_regions): New decl.
(class decl_region): Note that this is also used fo SSA names.
(decl_region::decl_region): Initialize m_tracked.
(decl_region::tracked_p): New.
(decl_region::calc_tracked_p): New decl.
(decl_region::m_tracked): New.
* store.cc (store::get_or_create_cluster): Assert that we
don't try to create clusters for base regions that aren't
trackable.
(store::mark_as_escaped): Don't mark base regions that we're not
tracking.
gcc/ChangeLog:
PR analyzer/104954
* doc/invoke.texi (Static Analyzer Options): Add
-fdump-analyzer-untracked.
gcc/testsuite/ChangeLog:
PR analyzer/104954
* gcc.dg/analyzer/asm-x86-dyndbg-1.c: New test.
* gcc.dg/analyzer/asm-x86-dyndbg-2.c: New test.
* gcc.dg/analyzer/many-unused-locals.c: New test.
* gcc.dg/analyzer/untracked-1.c: New test.
* gcc.dg/analyzer/unused-local-1.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/104979 reports a leak false positive when handling an
interprocedural return to a caller:
LHS = CALL(ARGS);
where the LHS is a certain non-trivial compound expression.
The root cause is that parts of the LHS were being erroneously
evaluated with respect to the stack frame of the called function,
rather than tha of the caller. When LHS contained a local variable
within the caller as part of certain nested expressions, this local
variable was looked for within the called frame, rather than that of the
caller. This lookup in the wrong stack frame led to the local variable
being treated as uninitialized, and thus the write to LHS was considered
as writing to a garbage location, leading to the return value being
lost, and thus being considered as a leak.
The region_model code uses the analyzer's path_var class to try to
extend the tree type with stack depth information. Based on the above,
I think that the path_var class is fundamentally broken, but it's used
in a few other places in the analyzer, so I don't want to rip it out
until the next stage 1.
In the meantime, this patch reworks how region_model::pop_frame works so
that the destination region for an interprocedural return value is
computed after the frame is popped, so that the region_model has the
stack frame for the *caller* at that point. Doing so fixes the issue.
I attempted a more ambitious fix which moved the storing of the return
svalue into the destination region from region_model::pop_region into
region_model::update_for_return_gcall, with pop_frame returning the
return svalue. Unfortunately, this regressed g++.dg/analyzer/pr93212.C,
which returns a pointer into a stale frame.
unbind_region_and_descendents and poison_any_pointers_to_descendents are
only set up to poison regions with bindings into the stale frame, not
individual svalues, and updating that became more invasive than I'm
comfortable with in stage 4.
The patch also adds assertions to verify that we have the correct
function when looking up locals/SSA names in a stack frame. There
doesn't seem to be a general-purpose way to get at the function of an
SSA name, so the assertions go from SSA name to def-stmt to basic_block,
and from there use the analyzer's supergraph to get the function from
the basic_block. If there's a simpler way to do this, please let me know.
gcc/analyzer/ChangeLog:
PR analyzer/104979
* engine.cc (impl_run_checkers): Create the engine after the
supergraph, and pass the supergraph to the engine.
* region-model.cc (region_model::get_lvalue_1): Pass ctxt to
frame_region::get_region_for_local.
(region_model::update_for_return_gcall): Pass the lvalue for the
result to pop_frame as a tree, rather than as a region.
(region_model::pop_frame): Update for above change, determining
the destination region after the frame is popped and thus with
respect to the caller frame rather than the called frame.
Likewise, set the value of the region to the return value after
the frame is popped.
(engine::engine): Add supergraph pointer.
(selftest::test_stack_frames): Set the DECL_CONTECT of PARM_DECLs.
(selftest::test_get_representative_path_var): Likewise.
(selftest::test_state_merging): Likewise.
* region-model.h (region_model::pop_frame): Convert first param
from a const region * to a tree.
(engine::engine): Add param "sg".
(engine::m_sg): New field.
* region.cc: Include "analyzer/sm.h" and
"analyzer/program-state.h".
(frame_region::get_region_for_local): Add "ctxt" param.
Add assertions that VAR_DECLs are locals, and that expr is for the
correct function.
* region.h (frame_region::get_region_for_local): Add "ctxt" param.
gcc/testsuite/ChangeLog:
PR analyzer/104979
* gcc.dg/analyzer/boxed-malloc-1-29.c: Deleted test, moving the
now fixed test_29 to...
* gcc.dg/analyzer/boxed-malloc-1.c: ...here.
* gcc.dg/analyzer/stale-frame-1.c: Add test coverage.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/105017
* sm-taint.cc (taint_diagnostic::subclass_equal_p): Check
m_has_bounds as well as m_arg.
(tainted_allocation_size::subclass_equal_p): Chain up to base
class implementation. Also check m_mem_space.
(tainted_allocation_size::emit): Add note showing stack-based vs
heap-based allocations.
gcc/testsuite/ChangeLog:
PR analyzer/105017
* gcc.dg/analyzer/taint-alloc-1.c: Add expected messages relating
to heap vs stack.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
PR analyzer/104997
* diagnostic-manager.cc (diagnostic_manager::add_diagnostic):
Convert return type from "void" to "bool", reporting success vs
failure to caller, for both overloads.
* diagnostic-manager.h (diagnostic_manager::add_diagnostic):
Likewise.
* engine.cc (impl_region_model_context::warn): Propagate return
value from diagnostic_manager::add_diagnostic.
gcc/testsuite/ChangeLog:
PR analyzer/104997
* gcc.dg/analyzer/write-to-string-literal-4-disabled.c: New test,
adapted from write-to-string-literal-4.c.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
The existing analyzer code attempts to purge the state of SSA names
where it can in order to minimize the size of program_state instances,
and to increase the chances of being able to reuse exploded_node
instances whilst exploring the user's code.
PR analyzer/104943 identifies that we fail to purge state of local
variables, based on behavior seen in PR analyzer/104954 when attempting
to profile slow performance of -fanalyzer on a particular file in the
Linux kernel, where that testcase has many temporary "boxed" values of
structs containing ints, which are never cleaned up, leading to bloat
of the program_state instances (specifically, of the store objects).
This patch generalizes the state purging from just being on SSA names
to also work on local variables. Doing so requires that we detect where
addresses to a local variable (or within them) are taken; we assume that
once a pointer has been taken, it's not longer safe to purge the value
of that decl at any successor point within the function.
Doing so speeds up the PR analyzer/104954 Linux kernel analyzer testcase
from taking 254 seconds to "just" 186 seconds (and I have a followup
patch in development that seems to further reduce this to 37 seconds).
The patch may also help with scaling up taint-detection so that it can
eventually be turned on by default, but we're not quite there (this
is PR analyzer/103533).
gcc/analyzer/ChangeLog:
PR analyzer/104943
PR analyzer/104954
PR analyzer/103533
* analyzer.h (class state_purge_per_decl): New forward decl.
* engine.cc (impl_run_checkers): Pass region_model_manager to
state_purge_map ctor.
* program-point.cc (function_point::final_stmt_p): New.
(function_point::get_next): New.
* program-point.h (function_point::final_stmt_p): New decl.
(function_point::get_next): New decl.
* program-state.cc (program_state::prune_for_point): Generalize to
purge local decls as well as SSA names.
(program_state::can_purge_base_region_p): New.
* program-state.h (program_state::can_purge_base_region_p): New
decl.
* region-model.cc (struct append_ssa_names_cb_data): Rename to...
(struct append_regions_cb_data): ...this.
(region_model::get_ssa_name_regions_for_current_frame): Rename
to...
(region_model::get_regions_for_current_frame): ...this, updating
for other renamings.
(region_model::append_ssa_names_cb): Rename to...
(region_model::append_regions_cb): ...this, and drop the requirement
that the subregion be a SSA name.
* region-model.h (struct append_ssa_names_cb_data): Rename decl
to...
(struct append_regions_cb_data): ...this.
(region_model::get_ssa_name_regions_for_current_frame): Rename
decl to...
(region_model::get_regions_for_current_frame): ...this.
(region_model::append_ssa_names_cb): Rename decl to...
(region_model::append_regions_cb): ...this.
* state-purge.cc: Include "tristate.h", "selftest.h",
"analyzer/store.h", "analyzer/region-model.h", and
"gimple-walk.h".
(get_candidate_for_purging): New.
(class gimple_op_visitor): New.
(my_load_cb): New.
(my_store_cb): New.
(my_addr_cb): New.
(state_purge_map::state_purge_map): Add "mgr" param. Update for
renamings. Find uses of local variables.
(state_purge_map::~state_purge_map): Update for renaming of m_map
to m_ssa_map. Clean up m_decl_map.
(state_purge_map::get_or_create_data_for_decl): New.
(state_purge_per_ssa_name::state_purge_per_ssa_name): Update for
inheriting from state_purge_per_tree.
(state_purge_per_ssa_name::add_to_worklist): Likewise.
(state_purge_per_decl::state_purge_per_decl): New.
(state_purge_per_decl::add_needed_at): New.
(state_purge_per_decl::add_pointed_to_at): New.
(state_purge_per_decl::process_worklists): New.
(state_purge_per_decl::add_to_worklist): New.
(same_binding_p): New.
(fully_overwrites_p): New.
(state_purge_per_decl::process_point_backwards): New.
(state_purge_per_decl::process_point_forwards): New.
(state_purge_per_decl::needed_at_point_p): New.
(state_purge_annotator::print_needed): Generalize to print local
decls as well as SSA names.
* state-purge.h (class state_purge_map): Update leading comment.
(state_purge_map::map_t): Rename to...
(state_purge_map::ssa_map_t): ...this.
(state_purge_map::iterator): Rename to...
(state_purge_map::ssa_iterator): ...this.
(state_purge_map::decl_map_t): New typedef.
(state_purge_map::decl_iterator): New typedef.
(state_purge_map::state_purge_map): Add "mgr" param.
(state_purge_map::get_data_for_ssa_name): Update for renaming.
(state_purge_map::get_any_data_for_decl): New.
(state_purge_map::get_or_create_data_for_decl): New decl.
(state_purge_map::begin): Rename to...
(state_purge_map::begin_ssas): ...this.
(state_purge_map::end): Rename to...
(state_purge_map::end_ssa): ...this.
(state_purge_map::begin_decls): New.
(state_purge_map::end_decls): New.
(state_purge_map::m_map): Rename to...
(state_purge_map::m_ssa_map): ...this.
(state_purge_map::m_decl_map): New field.
(class state_purge_per_tree): New class.
(class state_purge_per_ssa_name): Inherit from state_purge_per_tree.
(state_purge_per_ssa_name::get_function): Move to base class.
(state_purge_per_ssa_name::point_set_t): Likewise.
(state_purge_per_ssa_name::m_fun): Likewise.
(class state_purge_per_decl): New.
gcc/testsuite/ChangeLog:
PR analyzer/104943
PR analyzer/104954
PR analyzer/103533
* gcc.dg/analyzer/torture/boxed-ptr-1.c: Update expected number
of exploded nodes to reflect improvements in state purging.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
* state-purge.cc (state_purge_annotator::add_node_annotations):
Avoid duplicate before-supernode annotations when returning from
an interprocedural call. Show after-supernode annotations.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* program-point.cc (program_point::get_next): Fix missing
increment of index.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
Avoid generating execution paths for warnings that are ultimately
rejected due to -Wno-analyzer-* flags.
This improves the test case from taking at least several minutes
(before I killed it) to taking under a second.
This doesn't fix the slowdown seen in PR analyzer/104955 with large
numbers of warnings when the warnings are still enabled.
gcc/analyzer/ChangeLog:
PR analyzer/104955
* diagnostic-manager.cc (get_emission_location): New.
(diagnostic_manager::diagnostic_manager): Initialize
m_num_disabled_diagnostics.
(diagnostic_manager::add_diagnostic): Reject diagnostics that
will eventually be rejected due to being disabled.
(diagnostic_manager::emit_saved_diagnostics): Log the number
of disabled diagnostics.
(diagnostic_manager::emit_saved_diagnostic): Split out logic for
determining emission location to get_emission_location.
* diagnostic-manager.h
(diagnostic_manager::m_num_disabled_diagnostics): New field.
* engine.cc (stale_jmp_buf::get_controlling_option): New.
(stale_jmp_buf::emit): Use it.
* pending-diagnostic.h
(pending_diagnostic::get_controlling_option): New vfunc.
* region-model.cc
(poisoned_value_diagnostic::get_controlling_option): New.
(poisoned_value_diagnostic::emit): Use it.
(shift_count_negative_diagnostic::get_controlling_option): New.
(shift_count_negative_diagnostic::emit): Use it.
(shift_count_overflow_diagnostic::get_controlling_option): New.
(shift_count_overflow_diagnostic::emit): Use it.
(dump_path_diagnostic::get_controlling_option): New.
(dump_path_diagnostic::emit): Use it.
(write_to_const_diagnostic::get_controlling_option): New.
(write_to_const_diagnostic::emit): Use it.
(write_to_string_literal_diagnostic::get_controlling_option): New.
(write_to_string_literal_diagnostic::emit): Use it.
* sm-file.cc (double_fclose::get_controlling_option): New.
(double_fclose::emit): Use it.
(file_leak::get_controlling_option): New.
(file_leak::emit): Use it.
* sm-malloc.cc (mismatching_deallocation::get_controlling_option):
New.
(mismatching_deallocation::emit): Use it.
(double_free::get_controlling_option): New.
(double_free::emit): Use it.
(possible_null_deref::get_controlling_option): New.
(possible_null_deref::emit): Use it.
(possible_null_arg::get_controlling_option): New.
(possible_null_arg::emit): Use it.
(null_deref::get_controlling_option): New.
(null_deref::emit): Use it.
(null_arg::get_controlling_option): New.
(null_arg::emit): Use it.
(use_after_free::get_controlling_option): New.
(use_after_free::emit): Use it.
(malloc_leak::get_controlling_option): New.
(malloc_leak::emit): Use it.
(free_of_non_heap::get_controlling_option): New.
(free_of_non_heap::emit): Use it.
* sm-pattern-test.cc (pattern_match::get_controlling_option): New.
(pattern_match::emit): Use it.
* sm-sensitive.cc
(exposure_through_output_file::get_controlling_option): New.
(exposure_through_output_file::emit): Use it.
* sm-signal.cc (signal_unsafe_call::get_controlling_option): New.
(signal_unsafe_call::emit): Use it.
* sm-taint.cc (tainted_array_index::get_controlling_option): New.
(tainted_array_index::emit): Use it.
(tainted_offset::get_controlling_option): New.
(tainted_offset::emit): Use it.
(tainted_size::get_controlling_option): New.
(tainted_size::emit): Use it.
(tainted_divisor::get_controlling_option): New.
(tainted_divisor::emit): Use it.
(tainted_allocation_size::get_controlling_option): New.
(tainted_allocation_size::emit): Use it.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/many-disabled-diagnostics.c: New test.
* gcc.dg/plugin/analyzer_gil_plugin.c
(gil_diagnostic::get_controlling_option): New.
(double_save_thread::emit): Use it.
(fncall_without_gil::emit): Likewise.
(pyobject_usage_without_gil::emit): Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
Testing cc1 on pr93032-mztools-unsigned-char.c
Benchmark #1: (without patch)
Time (mean ± σ): 338.8 ms ± 13.6 ms [User: 323.2 ms, System: 14.2 ms]
Range (min … max): 326.7 ms … 363.1 ms 10 runs
Benchmark #2: (with patch)
Time (mean ± σ): 332.3 ms ± 12.8 ms [User: 316.6 ms, System: 14.3 ms]
Range (min … max): 322.5 ms … 357.4 ms 10 runs
Summary
./cc1.new ran 1.02 ± 0.06 times faster than ./cc1.old
gcc/analyzer/ChangeLog:
* store.cc (store::store): Presize m_cluster_map.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/104863
* constraint-manager.cc (constraint_manager::add_constraint):
Refresh the EC IDs when adding constraints implied by offsets.
gcc/testsuite/ChangeLog:
PR analyzer/104863
* gcc.dg/analyzer/torture/pr104863.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
The previous patch extended
-Wanalyzer-write-to-const
-Wanalyzer-write-to-string-literal
to make use of __attribute__ ((access, ....), but the results could be
inscrutable.
This patch adds notes to such diagnostics to give the user a reason for
why the analyzer is complaining.
Example output:
test.c: In function 'main':
test.c:15:13: warning: write to string literal [-Wanalyzer-write-to-string-literal]
15 | if (getrandom((char *)test, sizeof(buf), GRND_RANDOM))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'main': event 1
|
| 15 | if (getrandom((char *)test, sizeof(buf), GRND_RANDOM))
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (1) write to string literal here
|
test.c:3:5: note: parameter 1 of 'getrandom' marked with attribute 'access (write_only, 1, 2)'
3 | int getrandom (void *__buffer, size_t __length,
| ^~~~~~~~~
Unfortunately we don't have location information for the attributes
themselves, just the function declaration, and there doesn't seem to be
a good way of getting at the location of the individual parameters from
the middle end (the C and C++ FEs both have get_fndecl_argument_location,
but the implementations are different).
gcc/analyzer/ChangeLog:
PR analyzer/104793
* analyzer.h (class pending_note): New forward decl.
* diagnostic-manager.cc (saved_diagnostic::saved_diagnostic):
Initialize m_notes.
(saved_diagnostic::operator==): Compare m_notes.
(saved_diagnostic::add_note): New.
(saved_diagnostic::emit_any_notes): New.
(diagnostic_manager::add_note): New.
(diagnostic_manager::emit_saved_diagnostic): Call emit_any_notes
after emitting the warning.
* diagnostic-manager.h (saved_diagnostic::add_note): New decl.
(saved_diagnostic::emit_any_notes): New decl.
(saved_diagnostic::m_notes): New field.
(diagnostic_manager::add_note): New decl.
* engine.cc (impl_region_model_context::add_note): New.
* exploded-graph.h (impl_region_model_context::add_note): New
decl.
* pending-diagnostic.h (class pending_note): New.
(class pending_note_subclass): New template.
* region-model.cc (class reason_attr_access): New.
(check_external_function_for_access_attr): Add class
annotating_ctxt and use it when checking region.
(noop_region_model_context::add_note): New.
* region-model.h (region_model_context::add_note): New vfunc.
(noop_region_model_context::add_note): New decl.
(class region_model_context_decorator): New.
(class note_adding_context): New.
gcc/testsuite/ChangeLog:
PR analyzer/104793
* gcc.dg/analyzer/write-to-const-2.c: Add dg-message directives
for expected notes.
* gcc.dg/analyzer/write-to-function-1.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-2.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-3.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-4.c: Likewise.
* gcc.dg/analyzer/write-to-string-literal-5.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch extends:
-Wanalyzer-write-to-const
-Wanalyzer-write-to-string-literal
so that they will check for __attribute__ ((access, ....) on calls to
externally-defined functions, and complain about read-only regions
pointed to by arguments marked with a "write_only" or "read_write"
attribute.
gcc/analyzer/ChangeLog:
PR analyzer/104793
* region-model.cc
(region_model::check_external_function_for_access_attr): New.
(region_model::handle_unrecognized_call): Call it.
* region-model.h
(region_model::check_external_function_for_access_attr): New decl.
(region_model::handle_unrecognized_call): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/104793
* gcc.dg/analyzer/write-to-const-2.c: New test.
* gcc.dg/analyzer/write-to-function-1.c: New test.
* gcc.dg/analyzer/write-to-string-literal-2.c: New test.
* gcc.dg/analyzer/write-to-string-literal-3.c: New test.
* gcc.dg/analyzer/write-to-string-literal-4.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/analyzer/ChangeLog:
* sm-taint.cc (taint_state_machine::check_for_tainted_size_arg):
Avoid generating duplicate saved_diagnostics by only handling the
rdwr_map entry for the ptrarg, not the duplicate entry for the
sizarg.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/taint-size-access-attr-1.c: Add
-fanalyzer-show-duplicate-count to options; verify that a
duplicate was not created for the tainted size.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/101983 reports what I thought were false positives
from -Wanalyzer-malloc-leak, but on closer inspection, the
analyzer is correctly reporting heap-allocated buffers that are
no longer reachable.
However, these "leaks" occur at the end of "main". The analyzer already
has some logic to avoid reporting leaks at the end of main, where the
leak is detected at the end of the EXIT basic block. However, in this case,
the leak is detected at the clobber in BB 2 here:
<bb 2> :
func (&res);
res ={v} {CLOBBER(eol)};
_4 = 0;
<bb 3> :
<L0>:
return _4;
where we have a chain BB 2 -> BB 3 -> EXIT BB.
This patch generalizes the "are we at the end of 'main'" detection to
handle such cases, silencing -Wanalyzer-malloc-leak on them.
There's a remaining issue where the analyzer unhelpfully describes one
of the leaking values as '<unknown>', rather than 'res.a', but I'm
leaving that for a followup (covered by PR analyzer/99771).
gcc/analyzer/ChangeLog:
PR analyzer/101983
* engine.cc (returning_from_function_p): New.
(impl_region_model_context::on_state_leak): Use it when rejecting
leaks at the return from "main".
gcc/testsuite/ChangeLog:
PR analyzer/101983
* gcc.dg/analyzer/pr101983-main.c: New test.
* gcc.dg/analyzer/pr101983-not-main.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
Like in r10-7215-g700d4cb08c88aec37c13e21e63dd61fd698baabc 2 years ago,
I've run
grep -v 'long long\|optab optab\|template template\|double double' *.{[chS],cc} */*.{[chS],cc} *.def config/*/* 2>/dev/null | grep ' \([a-zA-Z]\+\) \1 '
and for the cases that looked clearly wrong changed them, mostly by removing
one of the duplicated words but in some cases with other changes.
2022-03-07 Jakub Jelinek <jakub@redhat.com>
gcc/
* tree-ssa-propagate.cc: Fix up duplicated word issue in a comment.
* config/riscv/riscv.cc: Likewise.
* config/darwin.h: Likewise.
* config/i386/i386.cc: Likewise.
* config/aarch64/thunderx3t110.md: Likewise.
* config/aarch64/fractional-cost.h: Likewise.
* config/vax/vax.cc: Likewise.
* config/rs6000/pcrel-opt.md: Likewise.
* config/rs6000/predicates.md: Likewise.
* ctfc.h: Likewise.
* tree-ssa-uninit.cc: Likewise.
* value-relation.h: Likewise.
* gimple-range-gori.cc: Likewise.
* ipa-polymorphic-call.cc: Likewise.
* pointer-query.cc: Likewise.
* ipa-sra.cc: Likewise.
* internal-fn.cc: Likewise.
* varasm.cc: Likewise.
* gimple-ssa-warn-access.cc: Likewise.
gcc/analyzer/
* store.cc: Fix up duplicated word issue in a comment.
* analyzer.cc: Likewise.
* engine.cc: Likewise.
* sm-taint.cc: Likewise.
gcc/c-family/
* c-attribs.cc: Fix up duplicated word issue in a comment.
gcc/cp/
* cvt.cc: Fix up duplicated word issue in a comment.
* pt.cc: Likewise.
* module.cc: Likewise.
* coroutines.cc: Likewise.
gcc/fortran/
* trans-expr.cc: Fix up duplicated word issue in a comment.
* gfortran.h: Likewise.
* scanner.cc: Likewise.
gcc/jit/
* libgccjit.h: Fix up duplicated word issue in a comment.
|
|
|
|
PR analyzer/103521 reports that commit r12-5585-g132902177138c09803d639e12b1daebf2b9edddc
("analyzer: further false leak fixes due to overzealous state merging [PR103217]")
led to failures of gcc.dg/analyzer/pr93032-mztools.c on some targets,
where rather than reporting FILE * leaks, the analyzer would hit
complexity limits and give up.
The cause is that pr93032-mztools.c has some 'unsigned char' values that
are copied to 'char'. On targets where 'char' defaults to being signed,
this leads to casts, whereas on targets where 'char' defaults to being
unsigned, no casts are needed.
When the casts occur, various symbolic values within the loop (the
locals 'crc', 'cpsize', and 'uncpsize') become sufficiently complex as
to hit the --param=analyzer-max-svalue-depth= limit, and are treated as
UNKNOWN, allowing the analysis of the loop to quickly terminate, with
much of this state as UNKNOWN (but retaining the FILE * information, and
thus correctly reporting the FILE * leaks).
Without the casts, the symbolic values for these variables don't quite
hit the complexity limit, and the analyzer attempts to track these
values in the loop, leading to the analyzer eventually hitting the
per-program-point limit on the number of states, and giving up on
these execution paths, thus failing to report the FILE * leaks.
This patch tweaks the default value of the param:
--param=analyzer-max-svalue-depth=.
from 13 down to 12. This allows the pr93032-mztools.c testcase to
succeeed with both -fsigned-char and -funsigned-char, and thus allows
this integration test to succeed on both styles of target without
requiring extra command-line flags. The patch duplicates the test so
it runs with both -fsigned-char and -funsigned-char.
My hope is that this will allow similar cases to terminate loop analysis
earlier. I tried reducing it further, but doing so caused some test
cases to regress.
The tradeoff here is between:
(a) precision of individual states in the analysis, versus
(b) maximizing code-path coverage in the analysis
I can imagine a more nuanced approach that splits the current
per-program-point hard limit into soft and hard limits: on hitting the
soft limit at a program point, go into a less precise mode for states
at that program point, in the hope that we can fully explore execution
paths beyond it without hitting the hard limit, but this seems like
GCC 13 material.
Another possible future fix might be for the analysis plan to make an
attempt to prioritize parts of the code in an enode budget, rather than
setting the same hard limit uniformly across all program points.
gcc/analyzer/ChangeLog:
PR analyzer/103521
* analyzer.opt (-param=analyzer-max-svalue-depth=): Reduce from 13
to 12.
gcc/testsuite/ChangeLog:
PR analyzer/103521
* gcc.dg/analyzer/pr93032-mztools.c: Move to...
* gcc.dg/analyzer/pr93032-mztools-signed-char.c: ...this, adding
-fsigned-char to args, and...
* gcc.dg/analyzer/pr93032-mztools-unsigned-char.c: ...copy to here,
adding -funsigned-char to args.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
When testing -fanalyzer on openblas-0.3, I noticed slightly over 2000
false positives from -Wanalyzer-malloc-leak on code like this:
if( LAPACKE_lsame( vect, 'b' ) || LAPACKE_lsame( vect, 'p' ) ) {
pt_t = (lapack_complex_float*)
LAPACKE_malloc( sizeof(lapack_complex_float) *
ldpt_t * MAX(1,n) );
[...snip...]
}
[...snip lots of code...]
if( LAPACKE_lsame( vect, 'b' ) || LAPACKE_lsame( vect, 'q' ) ) {
LAPACKE_free( pt_t );
}
where LAPACKE_lsame is a char-comparison function implemented in a
different TU.
The analyzer naively considers the execution path where:
LAPACKE_lsame( vect, 'b' ) || LAPACKE_lsame( vect, 'p' )
is true at the malloc guard, but then false at the free guard, which
is thus a memory leak.
This patch makes -fanalyer respect __attribute__((const)), so that the
analyzer treats such functions as returning the same value when given
the same inputs.
I've filed https://github.com/xianyi/OpenBLAS/issues/3543 suggesting that
LAPACKE_lsame be annotated with __attribute__((const)); with that, and
with this patch, the false positives seem to be fixed.
gcc/analyzer/ChangeLog:
PR analyzer/104434
* analyzer.h (class const_fn_result_svalue): New decl.
* region-model-impl-calls.cc (call_details::get_manager): New.
* region-model-manager.cc
(region_model_manager::get_or_create_const_fn_result_svalue): New.
(region_model_manager::log_stats): Log
m_const_fn_result_values_map.
* region-model.cc (const_fn_p): New.
(maybe_get_const_fn_result): New.
(region_model::on_call_pre): Handle fndecls with
__attribute__((const)) by calling the above rather than making
a conjured_svalue.
* region-model.h (visitor::visit_const_fn_result_svalue): New.
(region_model_manager::get_or_create_const_fn_result_svalue): New
decl.
(region_model_manager::const_fn_result_values_map_t): New typedef.
(region_model_manager::m_const_fn_result_values_map): New field.
(call_details::get_manager): New decl.
* svalue.cc (svalue::cmp_ptr): Handle SK_CONST_FN_RESULT.
(const_fn_result_svalue::dump_to_pp): New.
(const_fn_result_svalue::dump_input): New.
(const_fn_result_svalue::accept): New.
* svalue.h (enum svalue_kind): Add SK_CONST_FN_RESULT.
(svalue::dyn_cast_const_fn_result_svalue): New.
(class const_fn_result_svalue): New.
(is_a_helper <const const_fn_result_svalue *>::test): New.
(template <> struct default_hash_traits<const_fn_result_svalue::key_t>):
New.
gcc/testsuite/ChangeLog:
PR analyzer/104434
* gcc.dg/analyzer/attr-const-1.c: New test.
* gcc.dg/analyzer/attr-const-2.c: New test.
* gcc.dg/analyzer/attr-const-3.c: New test.
* gcc.dg/analyzer/pr104434-const.c: New test.
* gcc.dg/analyzer/pr104434-nonconst.c: New test.
* gcc.dg/analyzer/pr104434.h: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/104576 tracks that we issue a false positive from
-Wanalyzer-use-of-uninitialized-value for the reproducers of PR 63311
when optimization is disabled.
The root cause is that the analyzer was considering that a call to
__builtin_sinf could have side-effects.
This patch fixes things by generalizing the handling for "pure"
functions to also consider "const" functions.
gcc/analyzer/ChangeLog:
PR analyzer/104576
* region-model.cc: Include "calls.h".
(region_model::on_call_pre): Use flags_from_decl_or_type to
generalize check for DECL_PURE_P to also check for ECF_CONST.
gcc/testsuite/ChangeLog:
PR analyzer/104576
* gcc.dg/analyzer/torture/uninit-pr63311.c: New test.
* gcc.dg/analyzer/uninit-pr104576.c: New test.
* gfortran.dg/analyzer/uninit-pr63311.f90: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/104560 reports various false positives from
-Wanalyzer-free-of-non-heap seen with rdma-core, on what's
effectively:
free (&ptr->field)
where in this case "field" is the first element of its struct, and thus
&ptr->field == ptr, and could be on the heap.
The root cause is due to malloc_state_machine::on_stmt making
"LHS = &EXPR;"
transition LHS from start to non_heap when EXPR is not a MEM_REF;
this assumption doesn't hold for the above case.
This patch eliminates that state transition, instead relying on
malloc_state_machine::get_default_state to detect regions known to
not be on the heap.
Doing so fixes the false positive, but eliminates some events relating
to free-of-alloca identifying the alloca, so the patch also reworks
free_of_non_heap to capture which region has been freed, adding
region creation events to diagnostic paths, so that the alloca calls
can be identified, and using the memory space of the region for more
precise wording of the diagnostic.
The improvement to malloc_state_machine::get_default_state also
means we now detect attempts to free VLAs, functions and code labels.
In doing so I spotted that I wasn't adding region creation events for
regions for global variables, and for cases where an allocation is the
last stmt within its basic block, so the patch also fixes these issues.
gcc/analyzer/ChangeLog:
PR analyzer/104560
* diagnostic-manager.cc (diagnostic_manager::build_emission_path):
Add region creation events for globals of interest.
(null_assignment_sm_context::get_old_program_state): New.
(diagnostic_manager::add_events_for_eedge): Move check for
changing dynamic extents from PK_BEFORE_STMT case to after the
switch on the dst_point's kind so that we can emit them for the
final stmt in a basic block.
* engine.cc (impl_sm_context::get_old_program_state): New.
* sm-malloc.cc (malloc_state_machine::get_default_state): Rewrite
detection of m_non_heap to use get_memory_space.
(free_of_non_heap::free_of_non_heap): Add freed_reg param.
(free_of_non_heap::subclass_equal_p): Update for changes to
fields.
(free_of_non_heap::emit): Drop m_kind in favor of
get_memory_space.
(free_of_non_heap::describe_state_change): Remove logic for
detecting alloca.
(free_of_non_heap::mark_interesting_stuff): Add region-creation of
m_freed_reg.
(free_of_non_heap::get_memory_space): New.
(free_of_non_heap::kind): Drop enum.
(free_of_non_heap::m_freed_reg): New field.
(free_of_non_heap::m_kind): Drop field.
(malloc_state_machine::on_stmt): Drop transition to m_non_heap.
(malloc_state_machine::handle_free_of_non_heap): New function,
split out from on_deallocator_call and on_realloc_call, adding
detection of the freed region.
(malloc_state_machine::on_deallocator_call): Use it.
(malloc_state_machine::on_realloc_call): Likewise.
* sm.h (sm_context::get_old_program_state): New vfunc.
gcc/testsuite/ChangeLog:
PR analyzer/104560
* g++.dg/analyzer/placement-new.C: Update expected wording.
* g++.dg/analyzer/pr100244.C: Likewise.
* gcc.dg/analyzer/attr-malloc-1.c (test_7): Likewise.
* gcc.dg/analyzer/malloc-1.c (test_24): Likewise.
(test_25): Likewise.
(test_26): Likewise.
(test_50a, test_50b, test_50c): New.
* gcc.dg/analyzer/malloc-callbacks.c (test_5): Update expected
wording.
* gcc.dg/analyzer/malloc-paths-8.c: Likewise.
* gcc.dg/analyzer/pr104560-1.c: New test.
* gcc.dg/analyzer/pr104560-2.c: New test.
* gcc.dg/analyzer/realloc-1.c (test_7): Updated expected wording.
* gcc.dg/analyzer/vla-1.c (test_2): New. Prune output from
-Wfree-nonheap-object.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/104524
* region-model-manager.cc
(region_model_manager::maybe_fold_sub_svalue): Only call
get_or_create_cast if type is non-NULL.
gcc/testsuite/ChangeLog:
PR analyzer/104524
* gcc.dg/analyzer/pr104524.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
There is false positive from -Wanalyzer-use-of-uninitialized-value on
gcc.dg/analyzer/pr102692.c here:
‘fix_overlays_before’: events 1-3
|
| 75 | while (tail
| | ~~~~
| 76 | && (tem = make_lisp_ptr (tail, 5),
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (1) following ‘false’ branch (when ‘tail’ is NULL)...
| 77 | (end = marker_position (XOVERLAY (tem)->end)) >= pos))
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|......
| 82 | if (!tail || end < prev || !tail->next)
| | ~~~~~ ~~~~~~~~~~
| | | |
| | | (3) use of uninitialized value ‘end’ here
| | (2) ...to here
|
The issue is that inner || of the conditionals have been folded within the
frontend from a chain of control flow:
5 │ if (tail == 0B) goto <D.1986>; else goto <D.1988>;
6 │ <D.1988>:
7 │ if (end < prev) goto <D.1986>; else goto <D.1989>;
8 │ <D.1989>:
9 │ _1 = tail->next;
10 │ if (_1 == 0B) goto <D.1986>; else goto <D.1987>;
11 │ <D.1986>:
to an OR expr (and then to a bitwise-or by the gimplifier):
5 │ _1 = tail == 0B;
6 │ _2 = end < prev;
7 │ _3 = _1 | _2;
8 │ if (_3 != 0) goto <D.1986>; else goto <D.1988>;
9 │ <D.1988>:
10 │ _4 = tail->next;
11 │ if (_4 == 0B) goto <D.1986>; else goto <D.1987>;
This happens for sufficiently simple conditionals in fold_truth_andor.
In particular, the (end < prev) is short-circuited without optimization,
but is evaluated with optimization, leading to the false positive.
Given how early this folding occurs, it seems the simplest fix is to
try to detect places where this optimization appears to have happened,
and suppress uninit warnings within the statement that would have
been short-circuited.
gcc/analyzer/ChangeLog:
PR analyzer/102692
* exploded-graph.h (impl_region_model_context::get_stmt): New.
* region-model.cc: Include "gimple-ssa.h", "tree-phinodes.h",
"tree-ssa-operands.h", and "ssa-iterators.h".
(within_short_circuited_stmt_p): New.
(region_model::check_for_poison): Don't warn about uninit values
if within_short_circuited_stmt_p.
* region-model.h (region_model_context::get_stmt): New vfunc.
(noop_region_model_context::get_stmt): New.
gcc/testsuite/ChangeLog:
PR analyzer/102692
* gcc.dg/analyzer/pr102692-2.c: New test.
* gcc.dg/analyzer/pr102692.c: Remove xfail. Remove -O2 from
options and move to...
* gcc.dg/analyzer/torture/pr102692.c: ...here.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
PR analyzer/104274 reports a false positive from
-Wanalyzer-use-of-uninitialized-value on hppa when passing
an empty struct as a function parameter.
pa_pass_by_reference returns true for empty structs, so the
call is turned into:
struct empty arg.0;
arg.0 = arg
called_function (arg.0);
by gimplify_parameters.
However, gimplify_modify_expr discards assignments statments
of empty types, so that we end up with:
struct empty arg.0;
called_function (arg.0);
which the analyzer considers to be a use of uninitialized "arg.0";
Given that gimplify_modify_expr will discard any assignments to
such types, it seems simplest for -Wanalyzer-use-of-uninitialized-value
to ignore values of empty types.
gcc/analyzer/ChangeLog:
PR analyzer/104274
* region-model.cc (region_model::check_for_poison): Ignore
uninitialized uses of empty types.
gcc/testsuite/ChangeLog:
PR analyzer/104274
* gcc.dg/analyzer/torture/empty-struct-1.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/98797
* region-model-manager.cc
(region_model_manager::maybe_fold_sub_svalue): Generalize getting
individual chars of a STRING_CST from element_region to any
subregion which is a concrete access of a single byte from its
parent region.
* region.cc (region::get_relative_concrete_byte_range): New.
* region.h (region::get_relative_concrete_byte_range): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/98797
* gcc.dg/analyzer/casts-1.c: Mark xfails as fixed; add further
test coverage for casts of string literals.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|