Age | Commit message (Collapse) | Author | Files | Lines |
|
PR analyzer/98575 describes an unexpected -Wanalyzer-malloc-leak false
positive from gcc.dg/analyzer/pr94851-1.c on glibc < 2.28.
The issue is that a getchar call gets inlined into a call to _IO_getc,
and "_IO_getc" is not in the set of FILE * functions the analyzer
"knows about". This leads to a global pointer
struct buf *curbp;
being treated as UNKNOWN after the call to _IO_getc. Later when a
malloced pointer is written to curbp->b_amark, the write is discarded
(since curbp is unknown) without noting that the pointer has escaped,
and so the pointer is erroneously treated as leaking when the function
returns.
This patch updates the handling of *UNKNOWN to treat pointers written
to them as having escaped, fixing the false positive.
The patch stops the leak warning in gcc.dg/analyzer/explode-1.c.
After merging states at the join-point after the first switch, pp has
UNKNOWN value, and so *pp is a write through UNKNOWN, which with this
patch is now treated as escaping - despite the fact that all possible
values for *pp are on the stack. There doesn't seem to be a good way
to fix this, and the testcase is an artifically constructed one, so the
patch simply removes the dg-warning directive.
gcc/analyzer/ChangeLog:
PR analyzer/98575
* store.cc (store::set_value): Treat a pointer written to *UNKNOWN
as having escaped.
gcc/testsuite/ChangeLog:
PR analyzer/98575
* gcc.dg/analyzer/explode-1.c: Remove expected leak warning.
* gcc.dg/analyzer/pr94851-2.c: New test.
* gcc.dg/analyzer/pr98575-1.c: New test.
|
|
|
|
PR analyzer/93355 tracks that -fanalyzer fails to report the FILE *
leak in read_alias_file in intl/localealias.c.
One reason for the failure is that read_alias_file is marked as
"static", and the path leading to the single call of
read_alias_file is falsely rejected as infeasible due to
PR analyzer/96374. I have been attempting to fix that bug, but
don't have a good solution yet.
Previously, -fanalyzer only directly explored "static" functions
if they were needed for call summaries, instead forcing them to
be indirectly explored, but if we have a feasibility bug like
above, we will fail to report any issues in a function that's
only called by such a falsely infeasible path.
It now seems wrong to me to reject directly exploring static
functions: even if there is currently no way to call a function,
it seems reasonable to warn about bugs within them, since
otherwise these latent bugs are a timebomb in the code.
Hence this patch reworks toplevel_function_p to directly explore
almost all functions, working around these feasiblity issues.
It introduces a naming convention that "__analyzer_"-prefixed
function names don't get directly explored, since this is
useful in the analyzer's DejaGnu-based tests.
This workaround gets PR analyzer/93355 closer to working, but
unfortunately there is a second instance of PR analyzer/96374
within read_alias_file itself which means even with this patch
-fanalyzer falsely rejects the path as infeasible.
Still, this ought to help in other cases, and simplifies the
implementation.
gcc/analyzer/ChangeLog:
PR analyzer/93355
PR analyzer/96374
* engine.cc (toplevel_function_p): Simplify so that
we only reject functions with a "__analyzer_" prefix.
(add_any_callbacks): Delete.
(exploded_graph::build_initial_worklist): Update for
dropped param of toplevel_function_p.
(exploded_graph::build_initial_worklist): Don't bother
looking for callbacks that are reachable from global
initializers.
gcc/testsuite/ChangeLog:
PR analyzer/93355
PR analyzer/96374
* gcc.dg/analyzer/conditionals-3.c: Add "__analyzer_"
prefix to support subroutines where necessary.
* gcc.dg/analyzer/data-model-1.c: Likewise.
* gcc.dg/analyzer/feasibility-1.c (called_by_test_6a): New.
(test_6a): New.
* gcc.dg/analyzer/params.c: Add "__analyzer_" prefix to support
subroutines where necessary.
* gcc.dg/analyzer/pr96651-2.c: Likewise.
* gcc.dg/analyzer/signal-4b.c: Likewise.
* gcc.dg/analyzer/single-field.c: Likewise.
* gcc.dg/analyzer/torture/conditionals-2.c: Likewise.
|
|
|
|
PR analyzer/98918 reports various false positives and state explosions
on correct code that frees nodes and other pointers in a singly-linked
list.
The issue is that state-merger in the loop leads to UNKNOWN_VALUEs,
and these are then erroneously used to form compound symbolic values
and regions, such as;
INIT_VAL((*UNKNOWN(struct marker *)).ref)
and:
(*INIT_VAL((*UNKNOWN(struct marker * *))))
The malloc state machine then treats these symbolic values as
identifying specific pointers, and thus e.g. erroneously reports a
double-free when
INIT_VAL((*UNKNOWN(struct marker *)).ref)
is freed twice (on subsequent iterations of the loop).
Similarly, the increasingly complex compound symbolic values have
sm-state which prevents state merging, and eventually lead to the
analysis hitting safety limits and stopping.
This patch makes various compound values involving UNKNOWN be
themselves UNKNOWN, resolving both the false positives and the state
explosions.
gcc/analyzer/ChangeLog:
PR analyzer/98918
* region-model-manager.cc
(region_model_manager::get_or_create_initial_value):
Fold the initial value of *UNKNOWN_PTR to an UNKNOWN value.
(region_model_manager::get_field_region): Fold the value
of UNKNOWN_PTR->FIELD to *UNKNOWN_PTR_OF_&FIELD_TYPE.
gcc/testsuite/ChangeLog:
PR analyzer/98918
* gcc.dg/analyzer/pr98918.c: New test.
|
|
|
|
This patch adds a simplification to analyzer paths for
repeated CFG edges generated from compound conditionals.
For example, it simplifies:
| 5 | if (a && b && c)
| | ^~~~~~~~~~~~
| | | | |
| | | | (4) ...to here
| | | | (5) following ‘true’ branch (when ‘c != 0’)...
| | | (2) ...to here
| | | (3) following ‘true’ branch (when ‘b != 0’)...
| | (1) following ‘true’ branch (when ‘a != 0’)...
| 6 | __analyzer_dump_path ();
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (6) ...to here
to:
| 5 | if (a && b && c)
| | ^
| | |
| | (1) following ‘true’ branch...
| 6 | __analyzer_dump_path ();
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (2) ...to here
gcc/analyzer/ChangeLog:
* checker-path.cc (event_kind_to_string): Handle
EK_START_CONSOLIDATED_CFG_EDGES and
EK_END_CONSOLIDATED_CFG_EDGES.
(start_consolidated_cfg_edges_event::get_desc): New.
(checker_path::cfg_edge_pair_at_p): New.
* checker-path.h (enum event_kind): Add
EK_START_CONSOLIDATED_CFG_EDGES and
EK_END_CONSOLIDATED_CFG_EDGES.
(class start_consolidated_cfg_edges_event): New class.
(class end_consolidated_cfg_edges_event): New class.
(checker_path::delete_events): New.
(checker_path::replace_event): New.
(checker_path::cfg_edge_pair_at_p): New decl.
* diagnostic-manager.cc (diagnostic_manager::prune_path): Call
consolidate_conditions.
(same_line_as_p): New.
(diagnostic_manager::consolidate_conditions): New.
* diagnostic-manager.h
(diagnostic_manager::consolidate_conditions): New decl.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/combined-conditionals-1.c: New test.
|
|
|
|
In dce6c58db87ebf7f4477bd3126228e73e4eeee97 msebor extended the
"malloc" attribute to support user-defined allocator/deallocator
pairs.
This patch extends the "malloc" checker within -fanalyzer to use
these attributes. It is based on an earlier patch:
'RFC: add "deallocated_by" attribute for use by analyzer'
https://gcc.gnu.org/pipermail/gcc-patches/2020-October/555544.html
which added a different attribute. The patch needed a lot of reworking
to support multiple deallocators per allocator.
My hope was that this would provide a minimal level of markup that would
support library-checking without requiring lots of further markup.
I attempted to use this to detect a memory leak within a Linux
driver (CVE-2019-19078), by adding the attribute to mark these fns:
extern struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);
extern void usb_free_urb(struct urb *urb);
where there is a leak of a "urb" on an error-handling path.
Unfortunately I ran into the problem that there are various other fns
that take "struct urb *" and the analyzer conservatively assumes that a
urb passed to them might or might not be freed and thus stops tracking
state for them.
Hence this will only detect issues for the simplest cases (without
adding another attribute).
gcc/analyzer/ChangeLog:
* analyzer.h (is_std_named_call_p): New decl.
* diagnostic-manager.cc (path_builder::get_sm): New.
(state_change_event_creator::state_change_event_creator): Add "pb"
param.
(state_change_event_creator::on_global_state_change): Don't consider
state changes affecting other state_machines.
(state_change_event_creator::on_state_change): Likewise.
(state_change_event_creator::m_pb): New field.
(diagnostic_manager::add_events_for_eedge): Pass pb to visitor
ctor.
* region-model-impl-calls.cc
(region_model::impl_deallocation_call): New.
* region-model.cc: Include "attribs.h".
(region_model::on_call_post): Handle fndecls referenced by
__attribute__((deallocated_by(FOO))).
* region-model.h (region_model::impl_deallocation_call): New decl.
* sm-malloc.cc: Include "stringpool.h" and "attribs.h". Add
leading comment.
(class api): Delete.
(enum resource_state): Update comment for change from api to
deallocator and deallocator_set.
(allocation_state::allocation_state): Drop api param. Add
"deallocators" and "deallocator".
(allocation_state::m_api): Drop field in favor of...
(allocation_state::m_deallocators): New field.
(allocation_state::m_deallocator): New field.
(enum wording): Add WORDING_DEALLOCATED.
(struct deallocator): New.
(struct standard_deallocator): New.
(struct custom_deallocator): New.
(struct deallocator_set): New.
(struct custom_deallocator_set): New.
(struct standard_deallocator_set): New.
(struct deallocator_set_map_traits): New.
(malloc_state_machine::m_malloc): Drop field
(malloc_state_machine::m_scalar_new): Likewise.
(malloc_state_machine::m_vector_new): Likewise.
(malloc_state_machine::m_free): New field
(malloc_state_machine::m_scalar_delete): Likewise.
(malloc_state_machine::m_vector_delete): Likewise.
(malloc_state_machine::deallocator_map_t): New typedef.
(malloc_state_machine::m_deallocator_map): New field.
(malloc_state_machine::deallocator_set_cache_t): New typedef.
(malloc_state_machine::m_custom_deallocator_set_cache): New field.
(malloc_state_machine::custom_deallocator_set_map_t): New typedef.
(malloc_state_machine::m_custom_deallocator_set_map): New field.
(malloc_state_machine::m_dynamic_sets): New field.
(malloc_state_machine::m_dynamic_deallocators): New field.
(api::api): Delete.
(deallocator::deallocator): New ctor.
(deallocator::hash): New.
(deallocator::dump_to_pp): New.
(deallocator::cmp): New.
(deallocator::cmp_ptr_ptr): New.
(standard_deallocator::standard_deallocator): New ctor.
(deallocator_set::deallocator_set): New ctor.
(deallocator_set::dump): New.
(custom_deallocator_set::custom_deallocator_set): New ctor.
(custom_deallocator_set::contains_p): New.
(custom_deallocator_set::maybe_get_single): New.
(custom_deallocator_set::dump_to_pp): New.
(standard_deallocator_set::standard_deallocator_set): New ctor.
(standard_deallocator_set::contains_p): New.
(standard_deallocator_set::maybe_get_single): New.
(standard_deallocator_set::dump_to_pp): New.
(start_p): New.
(class mismatching_deallocation): Update for conversion from api
to deallocator_set and deallocator.
(double_free::emit): Use %qs.
(class use_after_free): Update for conversion from api to
deallocator_set and deallocator.
(malloc_leak::describe_state_change): Only emit "allocated here" on
a start->nonnull transition, rather than on other transitions to
nonnull.
(allocation_state::dump_to_pp): Update for conversion from api to
deallocator_set.
(allocation_state::get_nonnull): Likewise.
(malloc_state_machine::malloc_state_machine): Likewise.
(malloc_state_machine::~malloc_state_machine): New.
(malloc_state_machine::add_state): Update for conversion from api
to deallocator_set.
(malloc_state_machine::get_or_create_custom_deallocator_set): New.
(malloc_state_machine::maybe_create_custom_deallocator_set): New.
(malloc_state_machine::get_or_create_deallocator): New.
(malloc_state_machine::on_stmt): Update for conversion from api
to deallocator_set. Handle "__attribute__((malloc(FOO)))", and
the special attribute set on FOO.
(malloc_state_machine::on_allocator_call): Update for conversion
from api to deallocator_set. Add "returns_nonnull" param and use
it to affect which state to transition to.
(malloc_state_machine::on_deallocator_call): Update for conversion
from api to deallocator_set.
gcc/ChangeLog:
* attribs.h (fndecl_dealloc_argno): New decl.
* builtins.c (call_dealloc_argno): Split out second half of
function into...
(fndecl_dealloc_argno): New.
* doc/extend.texi (Common Function Attributes): Document the
interaction between the analyzer and the malloc attribute.
* doc/invoke.texi (Static Analyzer Options): Likewise.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/attr-malloc-1.c: New test.
* gcc.dg/analyzer/attr-malloc-2.c: New test.
* gcc.dg/analyzer/attr-malloc-4.c: New test.
* gcc.dg/analyzer/attr-malloc-5.c: New test.
* gcc.dg/analyzer/attr-malloc-6.c: New test.
* gcc.dg/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c: New test.
* gcc.dg/analyzer/attr-malloc-misuses.c: New test.
|
|
|
|
I've been implementing a PyGTK viewer for the output of
-fdump-analyzer-json, to help me debug analyzer issues:
https://github.com/davidmalcolm/gcc-analyzer-viewer
The viewer is very much just a work in progress.
This patch adds some fields that were missing from the dump, and
fixes some mistakes I spotted whilst working on the viewer.
gcc/analyzer/ChangeLog:
* engine.cc (strongly_connected_components::to_json): New.
(worklist::to_json): New.
(exploded_graph::to_json): JSON-ify the worklist.
* exploded-graph.h (strongly_connected_components::to_json): New
decl.
(worklist::to_json): New decl.
* store.cc (store::to_json): Fix comment.
* supergraph.cc (supernode::to_json): Fix reference to
"returning_call" in comment. Add optional "fun" to JSON.
(edge_kind_to_string): New.
(superedge::to_json): Add "kind" to JSON.
|
|
gcc/analyzer/ChangeLog:
PR analyzer/98679
* analyzer.h (region_offset::operator==): Make const.
* pending-diagnostic.h (pending_diagnostic::equal_p): Likewise.
* store.h (binding_cluster::for_each_value): Likewise.
(binding_cluster::for_each_binding): Likewise.
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/98628
* store.cc (binding_cluster::make_unknown_relative_to): Don't mark
dereferenced unknown pointers as having escaped.
gcc/testsuite/ChangeLog:
PR analyzer/98628
* gcc.dg/analyzer/pr98628.c: New test.
|
|
|
|
lto-streamer-out.c's get_symbol_initial_value can return error_mark_node
rather than DECL_INITIAL as an optimization to avoid extra sections for
simple scalar values.
Add a check to the analyzer to handle such cases gracefully.
gcc/analyzer/ChangeLog:
PR analyzer/98580
* region.cc (decl_region::get_svalue_for_initializer): Gracefully
handle when LTO writes out DECL_INITIAL as error_mark_node.
gcc/testsuite/ChangeLog:
PR analyzer/98580
* gcc.dg/analyzer/pr98580-a.c: New test.
* gcc.dg/analyzer/pr98580-b.c: New test.
|
|
gcc/analyzer/ChangeLog:
PR analyzer/97074
* store.cc (binding_cluster::can_merge_p): Add "out_store" param
and pass to calls to binding_cluster::make_unknown_relative_to.
(binding_cluster::make_unknown_relative_to): Add "out_store"
param. Use it to mark base regions that are pointed to by
pointers that become unknown as having escaped.
(store::can_merge_p): Pass out_store to
binding_cluster::can_merge_p.
* store.h (binding_cluster::can_merge_p): Add "out_store" param.
(binding_cluster::make_unknown_relative_to): Likewise.
* svalue.cc (region_svalue::implicitly_live_p): New vfunc.
* svalue.h (region_svalue::implicitly_live_p): New vfunc decl.
gcc/testsuite/ChangeLog:
PR analyzer/97074
* gcc.dg/analyzer/pr97074.c: New test.
|
|
gcc/analyzer/ChangeLog:
PR analyzer/98564
* engine.cc (exploded_path::feasible_p): Add missing call to
bitmap_clear.
gcc/testsuite/ChangeLog:
PR analyzer/98564
* gcc.dg/analyzer/pr98564.c: New test.
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/97072
* region-model-reachability.cc (reachable_regions::init_cluster):
Convert symbolic region handling to a switch statement. Add cases
to handle SK_UNKNOWN and SK_CONJURED.
gcc/testsuite/ChangeLog:
PR analyzer/97072
* gcc.dg/analyzer/pr97072.c: New test.
|
|
|
|
-fsanitize=undefined with calls to nonnull functions
creates struct __ubsan_nonnull_arg_data instances
with CONSTRUCTORs for RECORD_TYPEs with NULL index values.
The analyzer was mistakenly using INTEGER_CST for these
fields, leading to ICEs.
Fix the issue by iterating through the fields in the type
for such cases, imitating similar logic in varasm.c's
output_constructor.
gcc/analyzer/ChangeLog:
PR analyzer/98293
* store.cc (binding_map::apply_ctor_to_region): When "index" is
NULL, iterate through the fields for RECORD_TYPEs, rather than
creating an INTEGER_CST index.
gcc/testsuite/ChangeLog:
PR analyzer/98293
* gcc.dg/analyzer/pr98293.c: New test.
|
|
|
|
Do this separately from all other Copyright updates, as ChangeLog files
can be modified only separately.
|
|
|
|
I broke the build with --disable-analyzer with
g:66dde7bc64b75d4a338266333c9c490b12d49825, due to:
../../src/gcc/analyzer/analyzer-pass.cc: In member function ‘virtual unsigned int {anonymous}::pass_analyzer::execute(function*)’:
../../src/gcc/analyzer/analyzer-pass.cc:86:3: error: ‘sorry_no_analyzer’ was not declared in this scope
86 | sorry_no_analyzer ();
| ^~~~~~~~~~~~~~~~~
Fixed by including the relevant header file.
Sorry about the breakage.
gcc/analyzer/ChangeLog:
* analyzer-pass.cc: Include "analyzer/analyzer.h" for the
declaration of sorry_no_analyzer; include "tree.h" and
"function.h" as these are needed by it.
|
|
This patch adds a new GCC plugin event: PLUGIN_ANALYZER_INIT, called
when -fanalyzer is starting, allowing for GCC plugins to register
additional state-machine-based checks within -fanalyzer. The idea
is that 3rd-party code might want to add domain-specific checks for
its own APIs - with the caveat that the analyzer is itself still
rather experimental.
As an example, the patch adds a proof-of-concept plugin to the testsuite
for checking CPython code: verifying that code that relinquishes
CPython's global interpreter lock doesn't attempt to do anything with
PyObjects in the sections where the lock isn't held. It also adds a
warning about nested releases of the lock, which is forbidden.
For example:
demo.c: In function 'foo':
demo.c:11:3: warning: use of PyObject '*(obj)' without the GIL
11 | Py_INCREF (obj);
| ^~~~~~~~~
'test': events 1-3
|
| 15 | void test (PyObject *obj)
| | ^~~~
| | |
| | (1) entry to 'test'
| 16 | {
| 17 | Py_BEGIN_ALLOW_THREADS
| | ~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (2) releasing the GIL here
| 18 | foo (obj);
| | ~~~~~~~~~
| | |
| | (3) calling 'foo' from 'test'
|
+--> 'foo': events 4-5
|
| 9 | foo (PyObject *obj)
| | ^~~
| | |
| | (4) entry to 'foo'
| 10 | {
| 11 | Py_INCREF (obj);
| | ~~~~~~~~~
| | |
| | (5) PyObject '*(obj)' used here without the GIL
|
Doing so requires adding some logic for ignoring macro expansions in
analyzer diagnostics, since the insides of Py_INCREF and
Py_BEGIN_ALLOW_THREADS are not of interest to the user for these cases.
gcc/analyzer/ChangeLog:
* analyzer-pass.cc (pass_analyzer::execute): Move sorry call to...
(sorry_no_analyzer): New.
* analyzer.h (class state_machine): New forward decl.
(class logger): New forward decl.
(class plugin_analyzer_init_iface): New.
(sorry_no_analyzer): New decl.
* checker-path.cc (checker_path::fixup_locations): New.
* checker-path.h (checker_event::set_location): New.
(checker_path::fixup_locations): New decl.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Call
checker_path::fixup_locations, and call fixup_location
on the primary location.
* engine.cc: Include "plugin.h".
(class plugin_analyzer_init_impl): New.
(impl_run_checkers): Invoke PLUGIN_ANALYZER_INIT callbacks.
* pending-diagnostic.h (pending_diagnostic::fixup_location): New
vfunc.
gcc/ChangeLog:
* doc/plugins.texi (Plugin callbacks): Add PLUGIN_ANALYZER_INIT.
* plugin.c (register_callback): Likewise.
(invoke_plugin_callbacks_full): Likewise.
* plugin.def (PLUGIN_ANALYZER_INIT): New event.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_gil_plugin.c: New test.
* gcc.dg/plugin/gil-1.c: New test.
* gcc.dg/plugin/gil.h: New header.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new plugin
and test.
|
|
|
|
CWE-690 is only for dereferencing an unchecked return value; for
other kinds of NULL dereference, use the parent classification, CWE-476.
gcc/analyzer/ChangeLog:
PR analyzer/97893
* sm-malloc.cc (null_deref::emit): Use CWE-476 rather than
CWE-690, as this isn't due to an unchecked return value.
(null_arg::emit): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/97893
* gcc.dg/analyzer/malloc-1.c: Add CWE-690 and CWE-476 codes to
expected output.
|
|
|
|
This patch adds a custom event to paths emitted by
-Wanalyzer-stale-setjmp-buffer highlighting the place where the
pertinent stack frame is popped, and updates the final event in
the path to reference this.
gcc/analyzer/ChangeLog:
* checker-path.h (checker_event::get_id_ptr): New.
* diagnostic-manager.cc (path_builder::path_builder): Add "sd"
param and use it to initialize new field "m_sd".
(path_builder::get_pending_diagnostic): New.
(path_builder::m_sd): New field.
(diagnostic_manager::emit_saved_diagnostic): Pass sd to
path_builder ctor.
(diagnostic_manager::add_events_for_superedge): Call new
maybe_add_custom_events_for_superedge vfunc.
* engine.cc (stale_jmp_buf::stale_jmp_buf): Add "setjmp_point"
param and use it to initialize new field "m_setjmp_point".
Initialize new field "m_stack_pop_event".
(stale_jmp_buf::maybe_add_custom_events_for_superedge): New vfunc
implementation.
(stale_jmp_buf::describe_final_event): New vfunc implementation.
(stale_jmp_buf::m_setjmp_point): New field.
(stale_jmp_buf::m_stack_pop_event): New field.
(exploded_node::on_longjmp): Pass setjmp_point to stale_jmp_buf
ctor.
* pending-diagnostic.h
(pending_diagnostic::maybe_add_custom_events_for_superedge): New
vfunc.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/setjmp-5.c: Update expected path output to show
an event where the pertinent stack frame is popped. Update
expected message from final event to reference this event.
|
|
This patch implements -Wanalyzer-shift-count-negative
and -Wanalyzer-shift-count-overflow, analogous to the C/C++
warnings -Wshift-count-negative and -Wshift-count-overflow, but
implemented via interprocedural path analysis rather than via parsing
in a front end, and thus capable of detecting interprocedural cases that the
warnings implemented in the front ends can miss.
gcc/analyzer/ChangeLog:
PR tree-optimization/97424
* analyzer.opt (Wanalyzer-shift-count-negative): New.
(Wanalyzer-shift-count-overflow): New.
* region-model.cc (class shift_count_negative_diagnostic): New.
(class shift_count_overflow_diagnostic): New.
(region_model::get_gassign_result): Complain about shift counts that
are negative or are >= the operand's type's width.
gcc/ChangeLog:
PR tree-optimization/97424
* doc/invoke.texi (Static Analyzer Options): Add
-Wno-analyzer-shift-count-negative and
-Wno-analyzer-shift-count-overflow.
(-Wno-analyzer-shift-count-negative): New.
(-Wno-analyzer-shift-count-overflow): New.
gcc/testsuite/ChangeLog:
PR tree-optimization/97424
* gcc.dg/analyzer/invalid-shift-1.c: New test.
|
|
|
|
gcc/analyzer/ChangeLog:
* constraint-manager.cc (constraint_manager::merge): Remove
unused code.
* constraint-manager.h: Likewise.
* program-state.cc (sm_state_map::sm_state_map): Likewise.
(program_state::program_state): Likewise.
(test_sm_state_map): Likewise.
* program-state.h: Likewise.
* region-model-reachability.cc (reachable_regions::reachable_regions): Likewise.
* region-model-reachability.h: Likewise.
* region-model.cc (region_model::handle_unrecognized_call): Likewise.
(region_model::get_reachable_svalues): Likewise.
(region_model::can_merge_with_p): Likewise.
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/97668
* svalue.cc (cmp_cst): Handle COMPLEX_CST.
gcc/testsuite/ChangeLog:
PR analyzer/97668
* gcc.dg/analyzer/pr97668.c: New test.
* gfortran.dg/analyzer/pr97668.f: New test.
|
|
|
|
gcc/analyzer/ChangeLog:
* program-state.cc (sm_state_map::on_liveness_change): Sort the
leaking svalues before calling on_state_leak.
(program_state::detect_leaks): Likewise when calling
on_svalue_leak.
* region-model-reachability.cc
(reachable_regions::mark_escaped_clusters): Likewise when
calling on_escaped_function.
|
|
gcc/analyzer/ChangeLog:
PR analyzer/97608
* region-model-reachability.cc (reachable_regions::handle_sval):
Operands of reachable reversible operations are reachable.
gcc/testsuite/ChangeLog:
PR analyzer/97608
* gcc.dg/analyzer/malloc-1.c (test_42d): New.
* gcc.dg/analyzer/pr97608.c: New test.
|
|
gcc/ChangeLog:
* Makefile.in (ANALYZER_OBJS): Add analyzer/complexity.o.
gcc/analyzer/ChangeLog:
* analyzer.h (class state_machine): New forward decl.
(class logger): Likewise.
(class visitor): Likewise.
* complexity.cc: New file, taken from svalue.cc.
* complexity.h: New file, taken from region-model.h.
* region-model.h: Include "analyzer/svalue.h" and
"analyzer/region.h". Move struct complexity to complexity.h.
Move svalue, its subclasses and supporting decls to svalue.h.
Move region, its subclasses and supporting decls to region.h.
* region.cc: Include "analyzer/region.h".
(symbolic_region::symbolic_region): Move here from region-model.h.
* region.h: New file, based on material from region-model.h.
* svalue.cc: Include "analyzer/svalue.h".
(complexity::complexity): Move to complexity.cc.
(complexity::from_pair): Likewise.
* svalue.h: New file, based on material from region-model.h.
|
|
gcc/analyzer/ChangeLog:
* program-state.cc (sm_state_map::print): Guard the printing of
the origin pointer with !flag_dump_noaddr.
* region.cc (string_region::dump_to_pp): Likewise for
m_string_cst.
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/97568
* region-model.cc (region_model::get_initial_value_for_global):
Move check that !DECL_EXTERNAL from here to...
* region.cc (decl_region::get_svalue_for_initializer): ...here,
using it to reject zero initialization.
gcc/testsuite/ChangeLog:
PR analyzer/97568
* gcc.dg/analyzer/pr97568.c: New test.
|
|
Casting to intptr_t states the intent of an integer to pointer cast
more clearly and ensures that the cast causes no loss of precision on
any platforms. LLP64 platforms eg. have a long value of 4 bytes and
pointer values of 8 bytes which may even cause compiler errors.
gcc/analyzer/ChangeLog:
PR analyzer/96608
* store.h (hash): Cast to intptr_t instead of long
|
|
This patch is a followup to the previous one, eliminating
non-determinism in the behavior of the analyzer (rather than just in
the logs), by sorting whenever the result previously depended on
pointer values. Tested as per the previous patch.
gcc/analyzer/ChangeLog:
* constraint-manager.cc (svalue_cmp_by_ptr): Delete.
(equiv_class::canonicalize): Use svalue::cmp_ptr_ptr instead.
(equiv_class_cmp): Eliminate pointer comparison.
* diagnostic-manager.cc (dedupe_key::comparator): If they are at
the same location, also compare epath ength and pending_diagnostic
kind.
* engine.cc (readability_comparator): If two path_vars have the
same readability, then impose an arbitrary ordering on them.
(worklist::key_t::cmp): If two points have the same plan ordering,
continue the comparison. Call sm_state_map::cmp rather than
comparing hash values.
* program-state.cc (sm_state_map::entry_t::cmp): New.
(sm_state_map::cmp): New.
* program-state.h (sm_state_map::entry_t::cmp): New decl.
(sm_state_map::elements): New.
(sm_state_map::cmp): New.
|
|
This patch and the followup eliminate various forms of non-determinism
in the analyzer due to changing pointer values.
This patch fixes churn seen when diffing analyzer logs. The patch
avoids embedding pointers in various places, and adds sorting when
dumping hash_set and hash_map for various analyzer types. Doing so
requires implementing a way to sort svalue instances, and assigning UIDs
to gimple statements.
Tested both patches together via a script that runs a testcase 100 times,
and then using diff and md5sum to verify that the results are consistent
in the face of address space randomization:
FILENAME=$1
rm $FILENAME.*
for i in `seq 1 100`; do
echo "iteration: $i"
./xgcc -B. -fanalyzer -c ../../src/gcc/testsuite/gcc.dg/analyzer/$FILENAME \
--Wanalyzer-too-complex \
-fdump-analyzer-supergraph \
-fdump-analyzer-exploded-graph \
-fdump-analyzer \
-fdump-noaddr \
-fdump-analyzer-exploded-nodes-2
mv $FILENAME.supergraph.dot $FILENAME.$i.supergraph.dot
mv $FILENAME.analyzer.txt $FILENAME.$i.analyzer.txt
mv $FILENAME.supergraph-eg.dot $FILENAME.$i.supergraph-eg.dot
mv $FILENAME.eg.txt $FILENAME.$i.eg.txt
mv $FILENAME.eg.dot $FILENAME.$i.eg.dot
done
gcc/analyzer/ChangeLog:
* engine.cc (setjmp_record::cmp): New.
(supernode_cluster::dump_dot): Avoid embedding pointer in cluster
name.
(supernode_cluster::cmp_ptr_ptr): New.
(function_call_string_cluster::dump_dot): Avoid embedding pointer
in cluster name. Sort m_map when dumping child clusters.
(function_call_string_cluster::cmp_ptr_ptr): New.
(root_cluster::dump_dot): Sort m_map when dumping child clusters.
* program-point.cc (function_point::cmp): New.
(function_point::cmp_ptr): New.
* program-point.h (function_point::cmp): New decl.
(function_point::cmp_ptr): New decl.
* program-state.cc (sm_state_map::print): Sort the values. Guard
the printing of pointers with !flag_dump_noaddr.
(program_state::prune_for_point): Sort the regions.
(log_set_of_svalues): Sort the values. Guard the printing of
pointers with !flag_dump_noaddr.
* region-model-manager.cc (log_uniq_map): Sort the values.
* region-model-reachability.cc (dump_set): New function template.
(reachable_regions::dump_to_pp): Use it.
* region-model.h (svalue::cmp_ptr): New decl.
(svalue::cmp_ptr_ptr): New decl.
(setjmp_record::cmp): New decl.
(placeholder_svalue::get_name): New accessor.
(widening_svalue::get_point): New accessor.
(compound_svalue::get_map): New accessor.
(conjured_svalue::get_stmt): New accessor.
(conjured_svalue::get_id_region): New accessor.
(region::cmp_ptrs): Rename to...
(region::cmp_ptr_ptr): ...this.
* region.cc (region::cmp_ptrs): Rename to...
(region::cmp_ptr_ptr): ...this.
* state-purge.cc
(state_purge_per_ssa_name::state_purge_per_ssa_name): Sort
m_points_needing_name when dumping.
* store.cc (concrete_binding::cmp_ptr_ptr): New.
(symbolic_binding::cmp_ptr_ptr): New.
(binding_map::cmp): New.
(get_sorted_parent_regions): Update for renaming of
region::cmp_ptrs to region::cmp_ptr_ptr.
(store::dump_to_pp): Likewise.
(store::to_json): Likewise.
(store::can_merge_p): Sort the base regions before considering
them.
* store.h (concrete_binding::cmp_ptr_ptr): New decl.
(symbolic_binding::cmp_ptr_ptr): New decl.
(binding_map::cmp): New decl.
* supergraph.cc (supergraph::supergraph): Assign UIDs to the
gimple stmts.
* svalue.cc (cmp_cst): New.
(svalue::cmp_ptr): New.
(svalue::cmp_ptr_ptr): New.
|
|
This was effectively checking for one beyond the limit, rather than
the limit itself.
Seen when fixing PR analyzer/97514.
gcc/analyzer/ChangeLog:
* engine.cc (exploded_graph::get_or_create_node): Fix off-by-one
when imposing param_analyzer_max_enodes_per_program_point limit.
|
|
This fixes an ICE seen e.g. with gcc.dg/analyzer/data-model-16.c when
enabling -fdump-analyzer.
gcc/analyzer/ChangeLog:
* region-model.cc (region_model::get_representative_path_var):
Implement case RK_LABEL.
* region-model.h (label_region::get_label): New accessor.
|
|
|
|
gcc/analyzer/ChangeLog:
PR analyzer/97514
* engine.cc (exploded_graph::add_function_entry): Handle failure
to create an enode, rather than asserting.
gcc/testsuite/ChangeLog:
PR analyzer/97514
* gcc.dg/analyzer/pr97514.c: New test.
|