aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
AgeCommit message (Collapse)AuthorFilesLines
2020-10-22analyzer: fix ICE on dtor [PR97489]David Malcolm1-0/+5
gcc/analyzer/ChangeLog: PR analyzer/97489 * engine.cc (exploded_graph::add_function_entry): Assert that we have a function body. (exploded_graph::on_escaped_function): Reject fndecls that don't have a function body. gcc/testsuite/ChangeLog: PR analyzer/97489 * g++.dg/analyzer/pr97489.C: New test.
2020-10-15Daily bump.GCC Administrator1-0/+16
2020-10-14analyzer: fix ICE on globals with unknown size [PR93388]David Malcolm2-21/+32
This patch fixes an ICE seen when attempting to build various existing tests in our testsuite with -fanalyzer, including gcc.c-torture/compile/980816-1.c. gcc/analyzer/ChangeLog: PR analyzer/93388 * region-model.cc (region_model::get_initial_value_for_global): Fall back to returning an initial_svalue if decl_region::get_svalue_for_initializer fails. * region.cc (decl_region::get_svalue_for_initializer): Don't attempt to create a compound_svalue if the region has an unknown size. gcc/testsuite/ChangeLog: PR analyzer/93388 * gcc.dg/analyzer/data-model-21.c: New test.
2020-10-14analyzer: fix build with ada [PR93723]David Malcolm1-1/+0
gcc/analyzer/ChangeLog: PR analyzer/93723 * store.cc (binding_map::apply_ctor_to_region): Remove redundant assertion.
2020-10-13Daily bump.GCC Administrator1-0/+55
2020-10-12analyzer: handle static callbacks [PR97258]David Malcolm6-14/+109
The analyzer's initial worklist was only populated with non-static functions in the TU (along with those that look promising for call summaries). Hence some static functions that were never explicitly called but could be called via function pointers were not being analyzed. This patch remedies this by ensuring that functions that escape as function pointers get added to the worklist, if they haven't been already. Another fix would be to simply analyze all functions that we have a body for, but too much of the testsuite relies on static test functions not being directly analyzed. gcc/analyzer/ChangeLog: PR analyzer/97258 * engine.cc (impl_region_model_context::on_escaped_function): New vfunc. (exploded_graph::add_function_entry): Use m_functions_with_enodes to implement idempotency. (add_any_callbacks): New. (exploded_graph::build_initial_worklist): Use the above to find callbacks that are reachable from global initializers. (exploded_graph::on_escaped_function): New. * exploded-graph.h (impl_region_model_context::on_escaped_function): New decl. (exploded_graph::on_escaped_function): New decl. (exploded_graph::m_functions_with_enodes): New field. * region-model-reachability.cc (reachable_regions::reachable_regions): Replace "store" param with "model" param; use it to initialize m_model. (reachable_regions::add): When getting the svalue for the region, call get_store_value on the model rather than using an initial value. (reachable_regions::mark_escaped_clusters): Add ctxt param and use it to call on_escaped_function when a function_region escapes. * region-model-reachability.h (reachable_regions::reachable_regions): Replace "store" param with "model" param. (reachable_regions::mark_escaped_clusters): Add ctxt param. (reachable_regions::m_model): New field. * region-model.cc (region_model::handle_unrecognized_call): Update for change in reachable_regions ctor. (region_model::handle_unrecognized_call): Pass ctxt to mark_escaped_clusters. (region_model::get_reachable_svalues): Update for change in reachable_regions ctor. (region_model::get_initial_value_for_global): Read-only variables keep their initial values. * region-model.h (region_model_context::on_escaped_function): New vfunc. (noop_region_model_context::on_escaped_function): New. gcc/testsuite/ChangeLog: PR analyzer/97258 * gcc.dg/analyzer/callbacks-1.c: New test. * gcc.dg/analyzer/callbacks-2.c: New test. * gcc.dg/analyzer/callbacks-3.c: New test.
2020-10-12analyzer: add warnings about writes to constant regions [PR95007]David Malcolm4-1/+133
This patch adds two new warnings: -Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal for code paths where the analyzer detects a write to a constant region. As noted in the documentation part of the patch, the analyzer doesn't prioritize detection of such writes, in that the state-merging logic will blithely lose the distinction between const and non-const regions. Hence false negatives are likely to arise due to state-merging. However, if the analyzer does happen to spot such a write, it seems worth reporting, hence this patch. gcc/analyzer/ChangeLog: * analyzer.opt (Wanalyzer-write-to-const): New. (Wanalyzer-write-to-string-literal): New. * region-model-impl-calls.cc (region_model::impl_call_memcpy): Call check_for_writable_region. (region_model::impl_call_memset): Likewise. (region_model::impl_call_strcpy): Likewise. * region-model.cc (class write_to_const_diagnostic): New. (class write_to_string_literal_diagnostic): New. (region_model::check_for_writable_region): New. (region_model::set_value): Call check_for_writable_region. * region-model.h (region_model::check_for_writable_region): New decl. gcc/ChangeLog: * doc/invoke.texi: Document -Wanalyzer-write-to-const and -Wanalyzer-write-to-string-literal. gcc/testsuite/ChangeLog: PR c/83347 PR middle-end/90404 PR analyzer/95007 * gcc.dg/analyzer/write-to-const-1.c: New test. * gcc.dg/analyzer/write-to-string-literal-1.c: New test.
2020-10-08Daily bump.GCC Administrator1-0/+9
2020-10-07analyzer: handle C++ argument numbers and "this" [PR97116]David Malcolm1-14/+47
gcc/analyzer/ChangeLog: PR analyzer/97116 * sm-malloc.cc (method_p): New. (describe_argument_index): New. (inform_nonnull_attribute): Use describe_argument_index. (possible_null_arg::describe_final_event): Likewise. (null_arg::describe_final_event): Likewise. gcc/testsuite/ChangeLog: PR analyzer/97116 * g++.dg/analyzer/pr97116.C: New test.
2020-09-30Daily bump.GCC Administrator1-0/+14
2020-09-29analyzer: fix signal-handler registration location [PR95188]David Malcolm1-6/+16
PR analyzer/95188 reports that diagnostics from -Wanalyzer-unsafe-call-within-signal-handler use the wrong source location when reporting the signal-handler registration event in the diagnostic_path. The diagnostics erroneously use the location of the first stmt in the basic block containing the call to "signal", rather than that of the call itself. Fixed thusly. gcc/analyzer/ChangeLog: PR analyzer/95188 * engine.cc (stmt_requires_new_enode_p): Split enodes before "signal" calls. gcc/testsuite/ChangeLog: PR analyzer/95188 * gcc.dg/analyzer/signal-registration-loc.c: New test.
2020-09-29analyzer: silence -Wsign-compare warningsDavid Malcolm2-4/+4
gcc/analyzer/ChangeLog: * constraint-manager.cc (constraint_manager::add_constraint_internal): Whitespace fixes. Silence -Wsign-compare warning. * engine.cc (maybe_process_run_of_before_supernode_enodes): Silence -Wsign-compare warning.
2020-09-29Daily bump.GCC Administrator1-0/+25
2020-09-28analyzer: add some missing FINAL OVERRIDEsDavid Malcolm1-4/+16
Spotted by cppcheck. gcc/analyzer/ChangeLog: * region-model.h (binop_svalue::dyn_cast_binop_svalue): Remove redundant "virtual". Add FINAL OVERRIDE. (widening_svalue::dyn_cast_widening_svalue): Add FINAL OVERRIDE. (compound_svalue::dyn_cast_compound_svalue): Likewise. (conjured_svalue::dyn_cast_conjured_svalue): Likewise.
2020-09-28analyzer: remove unused fieldDavid Malcolm1-1/+0
I added this field (and the struct itself) in the rewrite of region and value-handling (808f4dfeb3a95f50f15e71148e5c1067f90a126d), but the field was never used. Found by cppcheck. gcc/analyzer/ChangeLog: * diagnostic-manager.cc (null_assignment_sm_context::m_visitor): Remove unused field.
2020-09-28analyzer: fix ICE on non-pointer longjmp [PR97233]David Malcolm2-1/+5
gcc/analyzer/ChangeLog: PR analyzer/97233 * analyzer.cc (is_longjmp_call_p): Require the initial argument to be a pointer. * engine.cc (exploded_node::on_longjmp): Likewise. gcc/testsuite/ChangeLog: PR analyzer/97233 * gcc.dg/analyzer/pr97233.c: New test.
2020-09-28analyzer: fix sm_state_map::printDavid Malcolm1-1/+1
In 10fc42a8396072912e9d9d940fba25950b3fdfc5 I converted state_t from unsigned to const state *, but missed this comparison against 0. gcc/analyzer/ChangeLog: * program-state.cc (sm_state_map::print): Update check for m_global_state being the start state.
2020-09-27Daily bump.GCC Administrator1-0/+10
2020-09-25analyzer: fix ICEs treeifying offset_region [PR96646, PR96841]David Malcolm1-2/+5
gcc/analyzer/ChangeLog: PR analyzer/96646 PR analyzer/96841 * region-model.cc (region_model::get_representative_path_var): When handling offset_region, wrap the MEM_REF's first argument in an ADDR_EXPR of pointer type, rather than simply using the tree for the parent region. Require the MEM_REF's second argument to be an integer constant. gcc/testsuite/ChangeLog: PR analyzer/96646 PR analyzer/96841 * gcc.dg/analyzer/pr96646.c: New test. * gcc.dg/analyzer/pr96841.c: New test.
2020-09-25Daily bump.GCC Administrator1-0/+50
2020-09-23analyzer: add -fno-analyzer-feasibilityDavid Malcolm9-48/+185
This patch provides a new option "-fno-analyzer-feasibility" as a way to disable feasibility-checking of the constraints along the control flow paths for -fanalyzer diagnostics. I'm adding this in the hope of making it easier to debug issues involving the feasibility-checking logic. The patch adds a new rejected_constraint object which is captured if exploded_path::feasible_p fails, and adds logic that uses this to emit an additional custom_event within the checker_path for the diagnostic, showing where in the control flow path the diagnostic would have been rejected, and giving details of why. gcc/analyzer/ChangeLog: * analyzer.h (struct rejected_constraint): New decl. * analyzer.opt (fanalyzer-feasibility): New option. * diagnostic-manager.cc (path_builder::path_builder): Add "problem" param and use it to initialize new field. (path_builder::get_feasibility_problem): New accessor. (path_builder::m_feasibility_problem): New field. (dedupe_winners::add): Remove inversion of logic in "if" clause, swapping if/else suites. In the !feasible_p suite, inspect flag_analyzer_feasibility and add code to handle when this is off, accepting the infeasible path, but recording the feasibility_problem. (diagnostic_manager::emit_saved_diagnostic): Pass the feasibility_problem to the path_builder. (diagnostic_manager::add_events_for_eedge): If we have a feasibility_problem at this edge, use it to add a custom event. * engine.cc (exploded_path::feasible_p): Pass a rejected_constraint ** to model.maybe_update_for_edge and transfer ownership of any created instance to any feasibility_problem. (feasibility_problem::dump_to_pp): New. * exploded-graph.h (feasibility_problem::feasibility_problem): Drop "model" param; add rejected_constraint * param. (feasibility_problem::~feasibility_problem): New. (feasibility_problem::dump_to_pp): New decl. (feasibility_problem::m_model): Drop field. (feasibility_problem::m_rc): New field. * program-point.cc (function_point::get_location): Handle PK_BEFORE_SUPERNODE and PK_AFTER_SUPERNODE. * program-state.cc (program_state::on_edge): Pass NULL to new param of region_model::maybe_update_for_edge. * region-model.cc (region_model::add_constraint): New overload adding a rejected_constraint ** param. (region_model::maybe_update_for_edge): Add rejected_constraint ** param and pass it to the various apply_constraints_for_ calls. (region_model::apply_constraints_for_gcond): Add rejected_constraint ** param and pass it to add_constraint calls. (region_model::apply_constraints_for_gswitch): Likewise. (region_model::apply_constraints_for_exception): Likewise. (rejected_constraint::dump_to_pp): New. * region-model.h (region_model::maybe_update_for_edge): Add rejected_constraint ** param. (region_model::add_constraint): New overload adding a rejected_constraint ** param. (region_model::apply_constraints_for_gcond): Add rejected_constraint ** param. (region_model::apply_constraints_for_gswitch): Likewise. (region_model::apply_constraints_for_exception): Likewise. (struct rejected_constraint): New. gcc/ChangeLog: * doc/analyzer.texi (Analyzer Paths): Add note about -fno-analyzer-feasibility. * doc/invoke.texi (Static Analyzer Options): Add -fno-analyzer-feasibility. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/feasibility-2.c: New test.
2020-09-24Daily bump.GCC Administrator1-0/+26
2020-09-23analyzer: fix member call on null seen with ubsan [PR97178]David Malcolm3-8/+10
gcc/analyzer/ChangeLog: PR analyzer/97178 * engine.cc (impl_run_checkers): Update for change to ext_state ctor. * program-state.cc (selftest::test_sm_state_map): Pass an engine instance to ext_state ctor. (selftest::test_program_state_1): Likewise. (selftest::test_program_state_2): Likewise. (selftest::test_program_state_merging): Likewise. (selftest::test_program_state_merging_2): Likewise. * program-state.h (extrinsic_state::extrinsic_state): Remove NULL default value for "eng" param.
2020-09-23gcc/analyzer: Silence -Wpragma warns with GCC < 10Tobias Burnus3-1/+6
gcc/analyzer/ChangeLog: * analyzer-logging.cc: Guard '#pragma ... ignored "-Wformat-diag"' by '#if __GNUC__ >= 10' * analyzer.h: Likewise. * call-string.cc: Likewise.
2020-09-22analyzer: use switch in exploded_node::on_stmtDavid Malcolm1-54/+80
This patch replaces a sequence of dyn_cast to different gimple stmt types in exploded_node::on_stmt with a switch on the gimple_code. This makes clearer which kinds of stmt are currently treated as no-ops, as a precursor to handling them properly. No functional change intended. gcc/analyzer/ChangeLog: * engine.cc (exploded_node::on_stmt): Replace sequence of dyn_cast with switch.
2020-09-23Daily bump.GCC Administrator1-0/+83
2020-09-22analyzer: add -fdump-analyzer-jsonDavid Malcolm36-0/+794
I've found this useful for debugging state explosions in the analyzer. gcc/analyzer/ChangeLog: * analysis-plan.cc: Include "json.h". * analyzer.opt (fdump-analyzer-json): New. * call-string.cc: Include "json.h". (call_string::to_json): New. * call-string.h (call_string::to_json): New decl. * checker-path.cc: Include "json.h". * constraint-manager.cc: Include "json.h". (equiv_class::to_json): New. (constraint::to_json): New. (constraint_manager::to_json): New. * constraint-manager.h (equiv_class::to_json): New decl. (constraint::to_json): New decl. (constraint_manager::to_json): New decl. * diagnostic-manager.cc: Include "json.h". (saved_diagnostic::to_json): New. (diagnostic_manager::to_json): New. * diagnostic-manager.h (saved_diagnostic::to_json): New decl. (diagnostic_manager::to_json): New decl. * engine.cc: Include "json.h", <zlib.h>. (exploded_node::status_to_str): New. (exploded_node::to_json): New. (exploded_edge::to_json): New. (exploded_graph::to_json): New. (dump_analyzer_json): New. (impl_run_checkers): Call it. * exploded-graph.h (exploded_node::status_to_str): New decl. (exploded_node::to_json): New. (exploded_edge::to_json): New. (exploded_graph::to_json): New. * pending-diagnostic.cc: Include "json.h". * program-point.cc: Include "json.h". (program_point::to_json): New. * program-point.h (program_point::to_json): New decl. * program-state.cc: Include "json.h". (extrinsic_state::to_json): New. (sm_state_map::to_json): New. (program_state::to_json): New. * program-state.h (extrinsic_state::to_json): New decl. (sm_state_map::to_json): New decl. (program_state::to_json): New decl. * region-model-impl-calls.cc: Include "json.h". * region-model-manager.cc: Include "json.h". * region-model-reachability.cc: Include "json.h". * region-model.cc: Include "json.h". * region-model.h (svalue::to_json): New decl. (region::to_json): New decl. * region.cc: Include "json.h". (region::to_json: New. * sm-file.cc: Include "json.h". * sm-malloc.cc: Include "json.h". * sm-pattern-test.cc: Include "json.h". * sm-sensitive.cc: Include "json.h". * sm-signal.cc: Include "json.h". (signal_delivery_edge_info_t::to_json): New. * sm-taint.cc: Include "json.h". * sm.cc: Include "diagnostic.h", "tree-diagnostic.h", and "json.h". (state_machine::state::to_json): New. (state_machine::to_json): New. * sm.h (state_machine::state::to_json): New. (state_machine::to_json): New. * state-purge.cc: Include "json.h". * store.cc: Include "json.h". (binding_key::get_desc): New. (binding_map::to_json): New. (binding_cluster::to_json): New. (store::to_json): New. * store.h (binding_key::get_desc): New decl. (binding_map::to_json): New decl. (binding_cluster::to_json): New decl. (store::to_json): New decl. * supergraph.cc: Include "json.h". (supergraph::to_json): New. (supernode::to_json): New. (superedge::to_json): New. * supergraph.h (supergraph::to_json): New decl. (supernode::to_json): New decl. (superedge::to_json): New decl. * svalue.cc: Include "json.h". (svalue::to_json): New. gcc/ChangeLog: * doc/analyzer.texi (Other Debugging Techniques): Mention -fdump-analyzer-json. * doc/invoke.texi (Static Analyzer Options): Add -fdump-analyzer-json.
2020-09-22Daily bump.GCC Administrator1-0/+16
2020-09-21analyzer: fix ICE on bogus decl of memset [PR97130]David Malcolm3-2/+13
Verify that arguments are pointers before calling handling code that calls deref_rvalue on them. gcc/analyzer/ChangeLog: PR analyzer/97130 * region-model-impl-calls.cc (call_details::get_arg_type): New. * region-model.cc (region_model::on_call_pre): Check that the initial arg is a pointer before calling impl_call_memset and impl_call_strlen. * region-model.h (call_details::get_arg_type): New decl. gcc/testsuite/ChangeLog: PR analyzer/97130 * gcc.dg/analyzer/pr97130.c: New test.
2020-09-21analyzer: decls are not on the heapDavid Malcolm1-1/+3
Whilst debugging the remaining state explosion in PR analyzer/93355 I noticed that half of the states at an exploding program point had: 'malloc': {'&buf': 'non-heap'} whereas the other half didn't, presumably depending on whether the path to each enode had used this local buffer: char buf[400]; This patch tweaks malloc_state_machine::get_default_state to be smarter about this, so that we can implicitly treat pointers to decls as non-heap, preventing pointless differences between sm_state_map instances. With that, all of the states in question have equal (empty) malloc sm-state - though the state explosion continues for other reasons. gcc/analyzer/ChangeLog: PR analyzer/93355 * sm-malloc.cc (malloc_state_machine::get_default_state): Look at the base region when considering pointers. Treat pointers to decls as being non-heap.
2020-09-19Daily bump.GCC Administrator1-0/+10
2020-09-18analyzer: fix warning_event::get_desc for global state changesDavid Malcolm1-8/+21
When experimenting the a new state_machine with global state I noticed that the fallback handling in warning_event::get_desc assumes we have per-value states, and ICEs on global states. Fixed thusly. gcc/analyzer/ChangeLog: * checker-path.cc (warning_event::get_desc): Handle global state changes.
2020-09-18analyzer: handle strdup and strndupDavid Malcolm1-1/+3
gcc/analyzer/ChangeLog: * sm-malloc.cc (malloc_state_machine::on_stmt): Handle strdup and strndup as being malloc-like allocators. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/strdup-1.c: New test. * gcc.dg/analyzer/strndup-1.c: New test.
2020-09-17Daily bump.GCC Administrator1-0/+47
2020-09-16analyzer: fix state explosions due to SCC bugDavid Malcolm1-6/+16
Debugging the state explosion of the very large switch statement in gcc.dg/analyzer/pr96653.c showed that the worklist was failing to order the exploded nodes correctly; the in-edges at the join point after the switch were not getting processed together, but were instead being rocessed in smaller batches, bloating the exploded graph until the per-point limit was reached. The root cause turned out to be a bug in creating the strongly-connected components for the supergraph: the code was considering interprocedural edges as well as intraprocedural edges, leading to unpredictable misorderings of the SCC and worklist, leading to bloating of the exploded graph. This patch fixes the SCC creation so it only considers intraprocedural edges within the supergraph. It also tweaks worklist::key_t::cmp to give higher precedence to call_string over differences within a supernode, since enodes with different call_strings can't be merges. In practise, none of my test cases were affected by this latter change, though it seems to be the right thing to do. With this patch, the very large switch statement in gcc.dg/analyzer/pr96653.c is handled in a single call to exploded_graph::maybe_process_run_of_before_supernode_enodes: merged 358 in-enodes into 2 out-enode(s) at SN: 402 and that testcase no longer hits the per-program-point limits. gcc/analyzer/ChangeLog: * engine.cc (strongly_connected_components::strong_connect): Only consider intraprocedural edges when creating SCCs. (worklist::key_t::cmp): Add comment. Treat call_string differences as more important than differences of program_point within a supernode. gcc/testsuite/ChangeLog: PR analyzer/96653 * gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c: Update expected number of exploded nodes. * gcc.dg/analyzer/malloc-vs-local-1a.c: Update expected number of exploded nodes. * gcc.dg/analyzer/pr96653.c: Remove -Wno-analyzer-too-complex.
2020-09-16analyzer: show SCC ids in .dot dumpsDavid Malcolm2-2/+13
gcc/analyzer/ChangeLog: * engine.cc (supernode_cluster::dump_dot): Show the SCC id in the per-supernode clusters in FILENAME.eg.dot output. (exploded_graph_annotator::add_node_annotations): Show the SCC of the supernode in FILENAME.supernode.eg.dot output. * exploded-graph.h (worklist::scc_id): New. (exploded_graph::get_scc_id): New.
2020-09-16analyzer: bulk merger/processing of runs of nodes at CFG join pointsDavid Malcolm2-0/+211
Prior to this patch the analyzer worklist considered only one node or two nodes at a time, processing and/or merging state individually or pairwise. This could lead to explosions of merger nodes at CFG join points, especially after switch statements, which could have large numbers of in-edges, and thus large numbers of merger exploded_nodes could be created, exceeding the per-point limit and thus stopping analysis with -Wanalyzer-too-complex. This patch special-cases the handling for runs of consecutive nodes in the worklist at a CFG join point, processing and merging them all together. The patch fixes a state explosion seen in bzip2.c seen when attempting to reproduce PR analyzer/95188, in a switch statement in a loop for argument parsing. With this patch, the analyzer successfully consolidates the state after the argument parsing to a single exploded node. In gcc.dg/analyzer/pr96653.c there is a switch statement with over 300 cases which leads to hitting the per-point limit. With this patch the consolidation code doesn't manage to merge all of them due to other worklist-ordering bugs, and it still hits the per-point limits, but it does manage some very long consolidations: merged 2 in-enodes into 2 out-enode(s) at SN: 403 merged 2 in-enodes into 2 out-enode(s) at SN: 403 merged 2 in-enodes into 1 out-enode(s) at SN: 11 merged 29 in-enodes into 1 out-enode(s) at SN: 35 merged 6 in-enodes into 1 out-enode(s) at SN: 41 merged 31 in-enodes into 1 out-enode(s) at SN: 35 and with a followup patch to fix an SCC issue it manages: merged 358 in-enodes into 2 out-enode(s) at SN: 402 The patch appears to fix the failure on non-x86_64 of: gcc.dg/analyzer/pr93032-mztools.c (test for excess errors) which is PR analyzer/96616. Unfortunately, the patch introduces a memory leak false positive in gcc.dg/analyzer/pr94851-1.c, but this appears to be a pre-existing bug that was hidden by state-merging failures. gcc/analyzer/ChangeLog: * engine.cc (exploded_node::dump_dot): Show STATUS_BULK_MERGED. (exploded_graph::process_worklist): Call maybe_process_run_of_before_supernode_enodes. (exploded_graph::maybe_process_run_of_before_supernode_enodes): New. (exploded_graph_annotator::print_enode): Show STATUS_BULK_MERGED. * exploded-graph.h (enum exploded_node::status): Add STATUS_BULK_MERGED. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/bzip2-arg-parse-1.c: New test. * gcc.dg/analyzer/loop-n-down-to-1-by-1.c: Remove xfail. * gcc.dg/analyzer/pr94851-1.c: Add xfail.
2020-09-16analyzer: add program_point::get_nextDavid Malcolm3-20/+35
Avoid some future copy-and-paste by introducing a function. gcc/analyzer/ChangeLog: * engine.cc (exploded_graph::process_node) <case PK_BEFORE_SUPERNODE>: Simplify by using program_point::get_next. * program-point.cc (program_point::get_next): New. * program-point.h (program_point::get_next): New decl.
2020-09-16analyzer: show program point in -Wanalyzer-too-complexDavid Malcolm1-0/+1
I found this useful when debugging. gcc/analyzer/ChangeLog: * engine.cc (exploded_graph::get_or_create_node): Show the program point when issuing -Wanalyzer-too-complex due to hitting the per-program-point limit.
2020-09-16analyzer: getchar has no side-effectsDavid Malcolm1-0/+5
Seen whilst debugging another issue, where the analyzer was assuming conservatively that a call to getchar could clobber a global. This is handled for most of the other stdio functions by the list in sm-file.cc gcc/analyzer/ChangeLog: * region-model.cc (region_model::on_call_pre): Treat getchar as having no side-effects. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/getchar-1.c: New test.
2020-09-16Daily bump.GCC Administrator1-0/+7
2020-09-15analyzer: fix ICE when merging constraints w/o transitivity [PR96650]David Malcolm1-1/+9
PR analyzer/96650 reports an assertion failure when merging the intersection of two sets of constraints, due to the resulting constraints being infeasible. It turns out that the two input sets were each infeasible if transitivity were considered, but -fanalyzer-transitivity was off. However for this case, the merging code was "discovering" the transitive infeasibility of the intersection of the constraints even when -fanalyzer-transitivity is off, triggering an assertion failure. I attempted various fixes for this, but each of them would have introduced O(N^2) logic into the constraint-handling code into the -fno-analyzer-transitivity case (with N == the number of constraints). This patch fixes the ICE by tweaking the assertion, so that we silently drop such constraints if -fanalyzer-transitivity is off. gcc/analyzer/ChangeLog: PR analyzer/96650 * constraint-manager.cc (merger_fact_visitor::on_fact): Replace assertion that add_constraint succeeded with an assertion that if it fails, -fanalyzer-transitivity is off. gcc/testsuite/ChangeLog: PR analyzer/96650 * gcc.dg/analyzer/pr96650-1-notrans.c: New test. * gcc.dg/analyzer/pr96650-1-trans.c: New test. * gcc.dg/analyzer/pr96650-2-notrans.c: New test. * gcc.dg/analyzer/pr96650-2-trans.c: New test.
2020-09-15Daily bump.GCC Administrator1-0/+22
2020-09-14analyzer: add -param=analyzer-max-constraints=David Malcolm2-0/+7
On attempting to run the full test suite with -fanalyzer via make check RUNTESTFLAGS="-v -v --target_board=unix/-fanalyzer" I saw it get stuck on: gcc.c-torture/compile/20001226-1.c It turns out this was on a debug build, rather than a release build; but a release build with -fanalyzer took: real 1m33.689s user 1m30.239s sys 0m2.727s as compared to: real 0m2.361s user 0m2.107s sys 0m0.214s without -fanalyzer. This torture test performs 64 * 64 uniqely-coded comparisons between elements of a pair of arrays until it finds an element that's different, leading to an accumulation of 4096 constraints along the path where no difference is found. "perf" shows most of the time is spent in canonicalizing and copying constraint_manager instances, presumably as it copies and merges states with increasingly more complex sets of constraints as it analyzes further along the "no differences yet" path. This patch crudely works around this by adding a -param=analyzer-max-constraints= limit, defaulting to 20, above which constraints will be silently dropped. With this -fanalyzer takes: real 0m6.935s user 0m6.413s sys 0m0.396s on the above case. gcc/analyzer/ChangeLog: * analyzer.opt (-param=analyzer-max-constraints=): New param. * constraint-manager.cc (constraint_manager::add_constraint_internal): Silently reject attempts to add constraints when the above limit is reached.
2020-09-14analyzer: fix constraint explosion on many-cased switch [PR96653]David Malcolm1-33/+0
PR analyzer/96653 reports a CPU-time and memory explosion in -fanalyzer seen in Linux 5.9-rc1:drivers/media/v4l2-core/v4l2-ctrls.c on a switch statement with many cases. The issue is some old code in constraint_manager::get_or_add_equiv_class for ensuring that comparisons between equivalence classes containing constants work correctly. The old code added constraints for every pair of ECs containing constants, leading to O(N^2) constraints (for N constants). Given that get_or_add_equiv_class also involves O(N) comparisons, this led to at least O(N^3) CPU time, and O(N^2) memory consumption when handling the "default" case, where N is the number of other cases in the switch statement. The state rewrite of r11-2694-g808f4dfeb3a95f50f15e71148e5c1067f90a126d added checking for comparisons between constants, making these explicit constraints redundant, but failed to remove the code mentioned above. This patch removes it, fixing the blow-up of constraints in the default case. gcc/analyzer/ChangeLog: PR analyzer/96653 * constraint-manager.cc (constraint_manager::get_or_add_equiv_class): Don't accumulate transitive closure of all constraints on constants. gcc/testsuite/ChangeLog: PR analyzer/96653 * gcc.dg/analyzer/pr96653.c: New test.
2020-09-14analyzer: fix ICE on setjmp with non-pointer-type [PR97029]David Malcolm2-1/+5
gcc/analyzer/ChangeLog: PR analyzer/97029 * analyzer.cc (is_setjmp_call_p): Require the initial arg to be a pointer. * region-model.cc (region_model::deref_rvalue): Assert that the svalue is of pointer type. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/pr97029.c: New test.
2020-09-12Daily bump.GCC Administrator1-0/+19
2020-09-10analyzer: stricter handling of non-pure builtins [PR96798]David Malcolm3-0/+77
Amongst other things PR analyzer/96798 notes that region_model::on_call_pre treats any builtin that hasn't been coded yet as a no-op (albeit with an unknown return value), which is wrong for non-pure builtins. This patch updates that function's handling of such builtins so that it instead conservatively assumes that any escaped/reachable regions can be affected by the call, and implements enough handling of specific builtins to avoid regressing the testsuite (I hope). gcc/analyzer/ChangeLog: PR analyzer/96798 * region-model-impl-calls.cc (region_model::impl_call_memcpy): New. (region_model::impl_call_strcpy): New. * region-model.cc (region_model::on_call_pre): Flag unhandled builtins that are non-pure as having unknown side-effects. Implement BUILT_IN_MEMCPY, BUILT_IN_MEMCPY_CHK, BUILT_IN_STRCPY, BUILT_IN_STRCPY_CHK, BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_PUTC, BUILT_IN_PUTC_UNLOCKED, BUILT_IN_FPUTC, BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_FPUTS, BUILT_IN_FPUTS_UNLOCKED, BUILT_IN_FWRITE, BUILT_IN_FWRITE_UNLOCKED, BUILT_IN_PRINTF, BUILT_IN_PRINTF_UNLOCKED, BUILT_IN_PUTCHAR, BUILT_IN_PUTCHAR_UNLOCKED, BUILT_IN_PUTS, BUILT_IN_PUTS_UNLOCKED, BUILT_IN_VFPRINTF, BUILT_IN_VPRINTF. * region-model.h (region_model::impl_call_memcpy): New decl. (region_model::impl_call_strcpy): New decl. gcc/testsuite/ChangeLog: PR analyzer/96798 * gcc.dg/analyzer/memcpy-1.c: New test. * gcc.dg/analyzer/strcpy-1.c: New test.
2020-09-10Daily bump.GCC Administrator1-0/+223
2020-09-09analyzer: generalize sm-malloc to new/delete [PR94355]David Malcolm6-115/+589
This patch generalizes the state machine in sm-malloc.c to support multiple allocator APIs, and adds just enough support for C++ new and delete to demonstrate the feature, allowing for detection of code paths where the result of new in C++ can leak - for some crude examples, at least (bearing in mind that the analyzer doesn't yet know about e.g. vfuncs, exceptions, inheritance, RTTI, etc) It also implements a new warning: -Wanalyzer-mismatching-deallocation. For example: demo.cc: In function 'void test()': demo.cc:8:8: warning: 'f' should have been deallocated with 'delete' but was deallocated with 'free' [CWE-762] [-Wanalyzer-mismatching-deallocation] 8 | free (f); | ~~~~~^~~ 'void test()': events 1-2 | | 7 | foo *f = new foo; | | ^~~ | | | | | (1) allocated here (expects deallocation with 'delete') | 8 | free (f); | | ~~~~~~~~ | | | | | (2) deallocated with 'free' here; allocation at (1) expects deallocation with 'delete' | The patch also adds just enough knowledge of exception-handling to suppress a false positive from -Wanalyzer-malloc-leak on g++.dg/analyzer/pr96723.C on the exception-handling CFG edge after operator new. It does this by adding a constraint that the result is NULL if an exception was thrown from operator new, since the result from operator new is lost when following that exception-handling CFG edge. gcc/analyzer/ChangeLog: PR analyzer/94355 * analyzer.opt (Wanalyzer-mismatching-deallocation): New warning. * region-model-impl-calls.cc (region_model::impl_call_operator_new): New. (region_model::impl_call_operator_delete): New. * region-model.cc (region_model::on_call_pre): Detect operator new and operator delete. (region_model::on_call_post): Likewise. (region_model::maybe_update_for_edge): Detect EH edges and call... (region_model::apply_constraints_for_exception): New function. * region-model.h (region_model::impl_call_operator_new): New decl. (region_model::impl_call_operator_delete): New decl. (region_model::apply_constraints_for_exception): New decl. * sm-malloc.cc (enum resource_state): New. (struct allocation_state): New state subclass. (enum wording): New. (struct api): New. (malloc_state_machine::custom_data_t): New typedef. (malloc_state_machine::add_state): New decl. (malloc_state_machine::m_unchecked) (malloc_state_machine::m_nonnull) (malloc_state_machine::m_freed): Delete these states in favor of... (malloc_state_machine::m_malloc) (malloc_state_machine::m_scalar_new) (malloc_state_machine::m_vector_new): ...this new api instances, which own their own versions of these states. (malloc_state_machine::on_allocator_call): New decl. (malloc_state_machine::on_deallocator_call): New decl. (api::api): New ctor. (dyn_cast_allocation_state): New. (as_a_allocation_state): New. (get_rs): New. (unchecked_p): New. (nonnull_p): New. (freed_p): New. (malloc_diagnostic::describe_state_change): Use unchecked_p and nonnull_p. (class mismatching_deallocation): New. (double_free::double_free): Add funcname param for initializing m_funcname. (double_free::emit): Use m_funcname in warning message rather than hardcoding "free". (double_free::describe_state_change): Likewise. Use freed_p. (double_free::describe_call_with_state): Use freed_p. (double_free::describe_final_event): Use m_funcname in message rather than hardcoding "free". (double_free::m_funcname): New field. (possible_null::describe_state_change): Use unchecked_p. (possible_null::describe_return_of_state): Likewise. (use_after_free::use_after_free): Add param for initializing m_api. (use_after_free::emit): Use m_api->m_dealloc_funcname in message rather than hardcoding "free". (use_after_free::describe_state_change): Use freed_p. Change the wording of the message based on the API. (use_after_free::describe_final_event): Use m_api->m_dealloc_funcname in message rather than hardcoding "free". Change the wording of the message based on the API. (use_after_free::m_api): New field. (malloc_leak::describe_state_change): Use unchecked_p. Update for renaming of m_malloc_event to m_alloc_event. (malloc_leak::describe_final_event): Update for renaming of m_malloc_event to m_alloc_event. (malloc_leak::m_malloc_event): Rename... (malloc_leak::m_alloc_event): ...to this. (free_of_non_heap::free_of_non_heap): Add param for initializing m_funcname. (free_of_non_heap::emit): Use m_funcname in message rather than hardcoding "free". (free_of_non_heap::describe_final_event): Likewise. (free_of_non_heap::m_funcname): New field. (allocation_state::dump_to_pp): New. (allocation_state::get_nonnull): New. (malloc_state_machine::malloc_state_machine): Update for changes to state fields and new api fields. (malloc_state_machine::add_state): New. (malloc_state_machine::on_stmt): Move malloc/calloc handling to on_allocator_call and call it, passing in the API pointer. Likewise for free, moving it to on_deallocator_call. Handle calls to operator new and delete in an analogous way. Use unchecked_p when testing for possibly-null-arg and possibly-null-deref, and transition to the non-null for the correct API. Remove redundant node param from call to on_zero_assignment. Use freed_p for use-after-free check, and pass in API. (malloc_state_machine::on_allocator_call): New, based on code in on_stmt. (malloc_state_machine::on_deallocator_call): Likewise. (malloc_state_machine::on_phi): Mark node param with ATTRIBUTE_UNUSED; don't pass it to on_zero_assignment. (malloc_state_machine::on_condition): Mark node param with ATTRIBUTE_UNUSED. Replace on_transition calls with get_state and set_next_state pairs, transitioning to the non-null state for the appropriate API. (malloc_state_machine::can_purge_p): Port to new state approach. (malloc_state_machine::on_zero_assignment): Replace on_transition calls with get_state and set_next_state pairs. Drop redundant node param. * sm.h (state_machine::add_custom_state): New. gcc/ChangeLog: PR analyzer/94355 * doc/invoke.texi: Document -Wanalyzer-mismatching-deallocation. gcc/testsuite/ChangeLog: PR analyzer/94355 * g++.dg/analyzer/new-1.C: New test. * g++.dg/analyzer/new-vs-malloc.C: New test.