aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
AgeCommit message (Collapse)AuthorFilesLines
2021-06-18analyzer: fix issue with symbolic reads with concrete bindingsDavid Malcolm1-0/+10
gcc/analyzer/ChangeLog: * store.cc (binding_cluster::get_any_binding): Make symbolic reads from a cluster with concrete bindings return unknown. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/symbolic-7.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-18analyzer: add region_model_manager::get_or_create_int_cstDavid Malcolm4-10/+20
gcc/analyzer/ChangeLog: * region-model-manager.cc (region_model_manager::get_or_create_int_cst): New. (region_model_manager::maybe_undo_optimize_bit_field_compare): Use it to simplify away a local tree. * region-model.cc (region_model::on_setjmp): Likewise. (region_model::on_longjmp): Likewise. * region-model.h (region_model_manager::get_or_create_int_cst): New decl. * store.cc (binding_cluster::zero_fill_region): Use it to simplify away a local tree. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-18analyzer: refactor custom_event, introducing precanned_custom_event classDavid Malcolm5-13/+26
I have followup work where a custom event's description would be better handled via a vfunc rather that a precanned string, hence this refactoring to make it easy to add custom_event subclasses. gcc/analyzer/ChangeLog: * checker-path.cc (class custom_event): Make abstract to allow for custom vfuncs, splitting existing implementation into... (class precanned_custom_event): New subclass. (custom_event::get_desc): Move to... (precanned_custom_event::get_desc): ...subclass. * checker-path.h (class custom_event): Make abstract to allow for custom vfuncs, splitting existing implementation into... (class precanned_custom_event): New subclass. * diagnostic-manager.cc (diagnostic_manager::add_events_for_eedge): Use precanned_custom_event. * engine.cc (stale_jmp_buf::maybe_add_custom_events_for_superedge): Likewise. * sm-signal.cc (signal_delivery_edge_info_t::add_events_to_path): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-16Daily bump.GCC Administrator1-0/+90
2021-06-15analyzer: fix bitfield endianness issues [PR99212,PR101082]David Malcolm5-35/+83
Looks like my patch for PR analyzer/99212 implicitly assumed little-endian, which the following patch fixes. Fixes bitfields-1.c on: - armeb-none-linux-gnueabihf - cris-elf - powerpc64-darwin - s390-linux-gnu gcc/analyzer/ChangeLog: PR analyzer/99212 PR analyzer/101082 * engine.cc: Include "target.h". (impl_run_checkers): Log BITS_BIG_ENDIAN, BYTES_BIG_ENDIAN, and WORDS_BIG_ENDIAN. * region-model-manager.cc (region_model_manager::maybe_fold_binop): Move support for masking via ARG0 & CST into... (region_model_manager::maybe_undo_optimize_bit_field_compare): ...this new function. Flatten by converting from nested conditionals to a series of early return statements to reject failures. Reject if type is not unsigned_char_type_node. Handle BYTES_BIG_ENDIAN when determining which bits are bound in the binding_map. * region-model.h (region_model_manager::maybe_undo_optimize_bit_field_compare): New decl. * store.cc (bit_range::dump): New function. * store.h (bit_range::dump): New decl. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-15analyzer: track dynamic extents of regionsDavid Malcolm7-42/+222
This patch extends region_model to add tracking of the sizes of dynamically-allocated regions, both on the heap (via malloc etc) and stack (via alloca). It adds enough purging of this state to avoid blowing up any existing analyzer test cases. The state can be queried via a new "__analyzer_dump_capacity" for use in DejaGnu tests but other than that doesn't do anything - I have various followup experiments that make use of this. gcc/analyzer/ChangeLog: * engine.cc (exploded_node::on_stmt): Handle __analyzer_dump_capacity. (exploded_node::on_stmt): Drop m_sm_changes from on_stmt_flags. (state_change_requires_new_enode_p): New function... (exploded_graph::process_node): Call it, rather than querying flags.m_sm_changes, so that dynamic-extent differences can also trigger the splitting of nodes. * exploded-graph.h (struct on_stmt_flags): Drop field m_sm_changes. * program-state.cc (program_state::detect_leaks): Purge dead heap-allocated regions from dynamic extents. (selftest::test_program_state_1): Fix type of "size_in_bytes". (selftest::test_program_state_merging): Likewise. * region-model-impl-calls.cc (region_model::impl_call_analyzer_dump_capacity): New. (region_model::impl_call_free): Remove dynamic extents from the freed region. * region-model-reachability.h (reachable_regions::begin_mutable_base_regs): New. (reachable_regions::end_mutable_base_regs): New. * region-model.cc: Include "tree-object-size.h". (region_model::region_model): Support new field m_dynamic_extents. (region_model::operator=): Likewise. (region_model::operator==): Likewise. (region_model::dump_to_pp): Dump sizes of dynamic regions. (region_model::handle_unrecognized_call): Purge dynamic extents from any regions that have escaped mutably:. (region_model::get_capacity): New function. (region_model::add_constraint): Unset dynamic extents when a heap-allocated region's address is NULL. (region_model::unbind_region_and_descendents): Purge dynamic extents of unbound regions. (region_model::can_merge_with_p): Call m_dynamic_extents.can_merge_with_p. (region_model::create_region_for_heap_alloc): Assert that size_in_bytes's type is compatible with size_type_node. Update for renaming of record_dynamic_extents to set_dynamic_extents. (region_model::create_region_for_alloca): Likewise. (region_model::record_dynamic_extents): Rename to... (region_model::set_dynamic_extents): ...this. Assert that size_in_bytes's type is compatible with size_type_node. Add it to the m_dynamic_extents map. (region_model::get_dynamic_extents): New. (region_model::unset_dynamic_extents): New. (selftest::test_state_merging): Fix type of "size". (selftest::test_malloc_constraints): Likewise. (selftest::test_malloc): Verify dynamic extents. (selftest::test_alloca): Likewise. * region-model.h (region_to_value_map::is_empty): New. (region_model::dynamic_extents_t): New typedef. (region_model::impl_call_analyzer_dump_capacity): New decl. (region_model::get_dynamic_extents): New function. (region_model::get_dynamic_extents): New decl. (region_model::set_dynamic_extents): New decl. (region_model::unset_dynamic_extents): New decl. (region_model::get_capacity): New decl. (region_model::record_dynamic_extents): Rename to set_dynamic_extents. (region_model::m_dynamic_extents): New field. gcc/ChangeLog: * doc/analyzer.texi (Special Functions for Debugging the Analyzer): Add __analyzer_dump_capacity. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_capacity): New decl. * gcc.dg/analyzer/capacity-1.c: New test. * gcc.dg/analyzer/capacity-2.c: New test. * gcc.dg/analyzer/capacity-3.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-15analyzer: add class region_to_value_mapDavid Malcolm2-0/+155
Add a class for associating symbolic values with regions, for use initially for recording the sizes of dynamically-allocated regions, though this also could potentially be used for e.g. tracking strlen() values. gcc/analyzer/ChangeLog: * region-model.cc (region_to_value_map::operator=): New. (region_to_value_map::operator==): New. (region_to_value_map::dump_to_pp): New. (region_to_value_map::dump): New. (region_to_value_map::can_merge_with_p): New. * region-model.h (class region_to_value_map): New class. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-14Daily bump.GCC Administrator1-0/+19
2021-06-13use range based for loops to iterate over vec<>Trevor Saunders6-46/+16
This changes users of FOR_EACH_VEC_ELT to use range based for loops, where the index variables are otherwise unused. As such the index variables are all deleted, producing shorter and simpler code. Signed-off-by: Trevor Saunders <tbsaunde@tbsaunde.org> gcc/analyzer/ChangeLog: * call-string.cc (call_string::call_string): Use range based for to iterate over vec<>. (call_string::to_json): Likewise. (call_string::hash): Likewise. (call_string::calc_recursion_depth): Likewise. * checker-path.cc (checker_path::fixup_locations): Likewise. * constraint-manager.cc (equiv_class::equiv_class): Likewise. (equiv_class::to_json): Likewise. (equiv_class::hash): Likewise. (constraint_manager::to_json): Likewise. * engine.cc (impl_region_model_context::on_svalue_leak): Likewise. (on_liveness_change): Likewise. (impl_region_model_context::on_unknown_change): Likewise. * program-state.cc (sm_state_map::set_state): Likewise. * region-model.cc (test_canonicalization_4): Likewise. gcc/ChangeLog: * attribs.c (find_attribute_namespace): Iterate over vec<> with range based for. * auto-profile.c (afdo_find_equiv_class): Likewise. * gcc.c (do_specs_vec): Likewise. (do_spec_1): Likewise. (driver::set_up_specs): Likewise. * gimple-loop-jam.c (any_access_function_variant_p): Likewise. * gimple-ssa-store-merging.c (compatible_load_p): Likewise. (imm_store_chain_info::try_coalesce_bswap): Likewise. (imm_store_chain_info::coalesce_immediate_stores): Likewise. (get_location_for_stmts): Likewise. * graphite-poly.c (print_iteration_domains): Likewise. (free_poly_bb): Likewise. (remove_gbbs_in_scop): Likewise. (free_scop): Likewise. (dump_gbb_cases): Likewise. (dump_gbb_conditions): Likewise. (print_pdrs): Likewise. (print_scop): Likewise. * ifcvt.c (cond_move_process_if_block): Likewise. * lower-subreg.c (decompose_multiword_subregs): Likewise. * regcprop.c (pass_cprop_hardreg::execute): Likewise. * sanopt.c (sanitize_rewrite_addressable_params): Likewise. * sel-sched-dump.c (dump_insn_vector): Likewise. * store-motion.c (store_ops_ok): Likewise. (store_killed_in_insn): Likewise. * timevar.c (timer::named_items::print): Likewise. * tree-cfgcleanup.c (cleanup_control_flow_pre): Likewise. (cleanup_tree_cfg_noloop): Likewise. * tree-data-ref.c (dump_data_references): Likewise. (print_dir_vectors): Likewise. (print_dist_vectors): Likewise. (dump_data_dependence_relations): Likewise. (dump_dist_dir_vectors): Likewise. (dump_ddrs): Likewise. (create_runtime_alias_checks): Likewise. (free_subscripts): Likewise. (save_dist_v): Likewise. (save_dir_v): Likewise. (invariant_access_functions): Likewise. (same_access_functions): Likewise. (access_functions_are_affine_or_constant_p): Likewise. (find_data_references_in_stmt): Likewise. (graphite_find_data_references_in_stmt): Likewise. (free_dependence_relations): Likewise. (free_data_refs): Likewise. * tree-inline.c (copy_debug_stmts): Likewise. * tree-into-ssa.c (dump_currdefs): Likewise. (rewrite_update_phi_arguments): Likewise. * tree-ssa-propagate.c (clean_up_loop_closed_phi): Likewise. * tree-vect-data-refs.c (vect_analyze_possibly_independent_ddr): Likewise. (vect_slp_analyze_node_dependences): Likewise. (vect_slp_analyze_instance_dependence): Likewise. (vect_record_base_alignments): Likewise. (vect_get_peeling_costs_all_drs): Likewise. (vect_peeling_supportable): Likewise. * tree-vectorizer.c (vec_info::~vec_info): Likewise. (vec_info::free_stmt_vec_infos): Likewise. gcc/cp/ChangeLog: * constexpr.c (cxx_eval_call_expression): Iterate over vec<> with range based for. (cxx_eval_store_expression): Likewise. (cxx_eval_loop_expr): Likewise. * decl.c (wrapup_namespace_globals): Likewise. (cp_finish_decl): Likewise. (cxx_simulate_enum_decl): Likewise. * parser.c (cp_parser_postfix_expression): Likewise.
2021-06-12Daily bump.GCC Administrator1-0/+5
2021-06-11analyzer: tweak priority of callstrings in worklist::key_t::cmpDavid Malcolm1-6/+19
While debugging another issue I noticed that the analyzer could fail to merge nodes for control flow in which one path had called a function and another path hadn't: BB / \ / \ fn call no fn call \ / \ / join BB The root cause was that the worklist sort function wasn't prioritizing call strings, and thus it was fully exploring the "no function called" path to the exit BB, and only then exploring the "within the function call" parts of the "funcion called" path. This patch prioritizes call strings when sorting the worklist so that the nodes with deeper call strings are processed before those with shallower call strings, thus allowing such nodes to be merged at the joinpoint. gcc/analyzer/ChangeLog: * engine.cc (worklist::key_t::cmp): Move sort by call_string to before SCC. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c: Update expected number of enodes after the loop. * gcc.dg/analyzer/paths-8.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-10Daily bump.GCC Administrator1-0/+15
2021-06-09analyzer: make various region_model member functions constDavid Malcolm2-16/+16
gcc/analyzer/ChangeLog: * region-model.cc (region_model::get_lvalue_1): Make const. (region_model::get_lvalue): Likewise. (region_model::get_rvalue_1): Likewise. (region_model::get_rvalue): Likewise. (region_model::deref_rvalue): Likewise. (region_model::get_rvalue_for_bits): Likewise. * region-model.h (region_model::get_lvalue): Likewise. (region_model::get_rvalue): Likewise. (region_model::deref_rvalue): Likewise. (region_model::get_rvalue_for_bits): Likewise. (region_model::get_lvalue_1): Likewise. (region_model::get_rvalue_1): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-09Daily bump.GCC Administrator1-0/+46
2021-06-08analyzer: bitfield fixes [PR99212]David Malcolm5-4/+315
This patch verifies the previous fix for bitfield sizes by implementing enough support for bitfields in the analyzer to get the test cases to pass. The patch implements support in the analyzer for reading from a BIT_FIELD_REF, and support for folding BIT_AND_EXPR of a mask, to handle the cases generated in tests. The existing bitfields tests in data-model-1.c turned out to rely on undefined behavior, in that they were assigning values to a signed bitfield that were outside of the valid range of values. I believe that that's why we were seeing target-specific differences in the test results (PR analyzer/99212). The patch updates the test to remove the undefined behaviors. gcc/analyzer/ChangeLog: PR analyzer/99212 * region-model-manager.cc (region_model_manager::maybe_fold_binop): Add support for folding BIT_AND_EXPR of compound_svalue and a mask constant. * region-model.cc (region_model::get_rvalue_1): Implement BIT_FIELD_REF in terms of... (region_model::get_rvalue_for_bits): New function. * region-model.h (region_model::get_rvalue_for_bits): New decl. * store.cc (bit_range::from_mask): New function. (selftest::test_bit_range_intersects_p): New selftest. (selftest::assert_bit_range_from_mask_eq): New. (ASSERT_BIT_RANGE_FROM_MASK_EQ): New macro. (selftest::assert_no_bit_range_from_mask_eq): New. (ASSERT_NO_BIT_RANGE_FROM_MASK): New macro. (selftest::test_bit_range_from_mask): New selftest. (selftest::analyzer_store_cc_tests): Call the new selftests. * store.h (bit_range::intersects_p): New. (bit_range::from_mask): New decl. (concrete_binding::get_bit_range): New accessor. (store_manager::get_concrete_binding): New overload taking const bit_range &. gcc/testsuite/ChangeLog: PR analyzer/99212 * gcc.dg/analyzer/bitfields-1.c: New test. * gcc.dg/analyzer/data-model-1.c (struct sbits): Make bitfields explicitly signed. (test_44): Update test values assigned to the bits to ones that fit in the range of the bitfield type. Remove xfails. (test_45): Remove xfails. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-08analyzer: fix region::get_bit_size for bitfieldsDavid Malcolm2-4/+31
gcc/analyzer/ChangeLog: * analyzer.h (int_size_in_bits): New decl. * region.cc (int_size_in_bits): New function. (region::get_bit_size): Reimplement in terms of the above. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-08analyzer: split out struct bit_range from class concrete_bindingDavid Malcolm2-22/+77
gcc/analyzer/ChangeLog: * store.cc (concrete_binding::dump_to_pp): Move bulk of implementation to... (bit_range::dump_to_pp): ...this new function. (bit_range::cmp): New. (concrete_binding::overlaps_p): Update for use of bit_range. (concrete_binding::cmp_ptr_ptr): Likewise. * store.h (struct bit_range): New. (class concrete_binding): Replace fields m_start_bit_offset and m_size_in_bits with new field m_bit_range. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-08analyzer: remove redundant typedefDavid Malcolm1-2/+0
Delete an overzealous copy&paste. gcc/analyzer/ChangeLog: * svalue.h (conjured_svalue::iterator_t): Delete. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-04Daily bump.GCC Administrator1-0/+10
2021-06-03analyzer: remove unused prototypesDavid Malcolm1-2/+0
gcc/analyzer/ChangeLog: * store.h (store::get_direct_binding): Remove unused decl. (store::get_default_binding): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-06-03analyzer: show types for poisoned_svalue and compound_svalueDavid Malcolm1-6/+23
gcc/analyzer/ChangeLog: * svalue.cc (poisoned_svalue::dump_to_pp): Dump type. (compound_svalue::dump_to_pp): Dump any type. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-05-19Daily bump.GCC Administrator1-0/+8
2021-05-18analyzer: fix missing leak after call to strsep [PR100615]David Malcolm1-0/+28
PR analyzer/100615 reports a missing leak diagnostic. The issue is that the code calls strsep which the analyzer doesn't have special knowledge of, and so conservatively assumes that it could free the pointer, so drops malloc state for it. Properly "teaching" the analyzer about strsep would require it to support bifurcating state at a call, which is currently fiddly to do, so for now this patch notes that strsep doesn't affect the malloc state machine, allowing the analyzer to correctly detect the leak. gcc/analyzer/ChangeLog: PR analyzer/100615 * sm-malloc.cc: Include "analyzer/function-set.h". (malloc_state_machine::on_stmt): Call unaffected_by_call_p and bail on the functions it recognizes. (malloc_state_machine::unaffected_by_call_p): New. gcc/testsuite/ChangeLog: PR analyzer/100615 * gcc.dg/analyzer/pr100615.c: New test.
2021-05-11Daily bump.GCC Administrator1-0/+13
2021-05-10Come up with startswith function.Martin Liska1-3/+2
gcc/ada/ChangeLog: * gcc-interface/utils.c (def_builtin_1): Use startswith function instead of strncmp. gcc/analyzer/ChangeLog: * sm-file.cc (is_file_using_fn_p): Use startswith function instead of strncmp. gcc/ChangeLog: * builtins.c (is_builtin_name): Use startswith function instead of strncmp. * collect2.c (main): Likewise. (has_lto_section): Likewise. (scan_libraries): Likewise. * coverage.c (coverage_checksum_string): Likewise. (coverage_init): Likewise. * dwarf2out.c (is_cxx): Likewise. (gen_compile_unit_die): Likewise. * gcc-ar.c (main): Likewise. * gcc.c (init_spec): Likewise. (read_specs): Likewise. (execute): Likewise. (check_live_switch): Likewise. * genattrtab.c (write_attr_case): Likewise. (IS_ATTR_GROUP): Likewise. * gencfn-macros.c (main): Likewise. * gengtype.c (type_for_name): Likewise. (gen_rtx_next): Likewise. (get_file_langdir): Likewise. (write_local): Likewise. * genmatch.c (get_operator): Likewise. (get_operand_type): Likewise. (expr::gen_transform): Likewise. * genoutput.c (validate_optab_operands): Likewise. * incpath.c (add_sysroot_to_chain): Likewise. * langhooks.c (lang_GNU_C): Likewise. (lang_GNU_CXX): Likewise. (lang_GNU_Fortran): Likewise. (lang_GNU_OBJC): Likewise. * lto-wrapper.c (run_gcc): Likewise. * omp-general.c (omp_max_simt_vf): Likewise. * omp-low.c (omp_runtime_api_call): Likewise. * opts-common.c (parse_options_from_collect_gcc_options): Likewise. * read-rtl-function.c (function_reader::read_rtx_operand_r): Likewise. * real.c (real_from_string): Likewise. * selftest.c (assert_str_startswith): Likewise. * timevar.c (timer::validate_phases): Likewise. * tree.c (get_file_function_name): Likewise. * ubsan.c (ubsan_use_new_style_p): Likewise. * varasm.c (default_function_rodata_section): Likewise. (incorporeal_function_p): Likewise. (default_section_type_flags): Likewise. * system.h (startswith): Define startswith. gcc/c-family/ChangeLog: * c-ada-spec.c (print_destructor): Use startswith function instead of strncmp. (dump_ada_declaration): Likewise. * c-common.c (disable_builtin_function): Likewise. (def_builtin_1): Likewise. * c-format.c (check_tokens): Likewise. (check_plain): Likewise. (convert_format_name_to_system_name): Likewise. gcc/c/ChangeLog: * c-aux-info.c (affix_data_type): Use startswith function instead of strncmp. * c-typeck.c (build_function_call_vec): Likewise. * gimple-parser.c (c_parser_gimple_parse_bb_spec): Likewise. gcc/cp/ChangeLog: * decl.c (duplicate_decls): Use startswith function instead of strncmp. (cxx_builtin_function): Likewise. (omp_declare_variant_finalize_one): Likewise. (grokfndecl): Likewise. * error.c (dump_decl_name): Likewise. * mangle.c (find_decomp_unqualified_name): Likewise. (write_guarded_var_name): Likewise. (decl_tls_wrapper_p): Likewise. * parser.c (cp_parser_simple_type_specifier): Likewise. (cp_parser_tx_qualifier_opt): Likewise. * pt.c (template_parm_object_p): Likewise. (dguide_name_p): Likewise. gcc/d/ChangeLog: * d-builtins.cc (do_build_builtin_fn): Use startswith function instead of strncmp. * dmd/dinterpret.c (evaluateIfBuiltin): Likewise. * dmd/dmangle.c: Likewise. * dmd/hdrgen.c: Likewise. * dmd/identifier.c (Identifier::toHChars2): Likewise. gcc/fortran/ChangeLog: * decl.c (variable_decl): Use startswith function instead of strncmp. (gfc_match_end): Likewise. * gfortran.h (gfc_str_startswith): Likewise. * module.c (load_omp_udrs): Likewise. (read_module): Likewise. * options.c (gfc_handle_runtime_check_option): Likewise. * primary.c (match_arg_list_function): Likewise. * trans-decl.c (gfc_get_symbol_decl): Likewise. * trans-expr.c (gfc_conv_procedure_call): Likewise. * trans-intrinsic.c (gfc_conv_ieee_arithmetic_function): Likewise. gcc/go/ChangeLog: * gofrontend/runtime.cc (Runtime::name_to_code): Use startswith function instead of strncmp. gcc/objc/ChangeLog: * objc-act.c (objc_string_ref_type_p): Use startswith function instead of strncmp. * objc-encoding.c (encode_type): Likewise. * objc-next-runtime-abi-02.c (has_load_impl): Likewise.
2021-05-10Remove __cplusplus >= 201103Martin Liska3-11/+0
Right now, we require a C++11 compiler, so the check is not needed any longer. gcc/analyzer/ChangeLog: * program-state.cc (program_state::operator=): Remove __cplusplus >= 201103. (program_state::program_state): Likewise. * program-state.h: Likewise. * region-model.h (class region_model): Remove dead code. gcc/ChangeLog: * bitmap.h (class auto_bitmap): Remove __cplusplus >= 201103. * config/aarch64/aarch64.c: Likewise. * gimple-ssa-store-merging.c (store_immediate_info::store_immediate_info): Likewise. * sbitmap.h: Likewise.
2021-04-25Daily bump.GCC Administrator1-0/+6
2021-04-24analyzer: fix ICE on NULL change.m_expr [PR100244]David Malcolm1-1/+1
PR analyzer/100244 reports an ICE on a -Wanalyzer-free-of-non-heap due to a case where free_of_non_heap::describe_state_change can be passed a NULL change.m_expr for a suitably complicated symbolic value. Bulletproof it by checking for change.m_expr being NULL before dereferencing it. gcc/analyzer/ChangeLog: PR analyzer/100244 * sm-malloc.cc (free_of_non_heap::describe_state_change): Bulletproof against change.m_expr being NULL. gcc/testsuite/ChangeLog: PR analyzer/100244 * g++.dg/analyzer/pr100244.C: New test.
2021-04-14Daily bump.GCC Administrator1-0/+12
2021-04-12gimple UIDs, LTO and -fanalyzer [PR98599]David Malcolm2-4/+68
gimple.h has this comment for gimple's uid field: /* UID of this statement. This is used by passes that want to assign IDs to statements. It must be assigned and used by each pass. By default it should be assumed to contain garbage. */ unsigned uid; and gimple_set_uid has: Please note that this UID property is supposed to be undefined at pass boundaries. This means that a given pass should not assume it contains any useful value when the pass starts and thus can set it to any value it sees fit. which suggests that any pass can use the uid field as an arbitrary scratch space. PR analyzer/98599 reports a case where this error occurs in LTO mode: fatal error: Cgraph edge statement index out of range on certain inputs with -fanalyzer. The error occurs in the LTRANS phase after -fanalyzer runs in the WPA phase. The analyzer pass writes to the uid fields of all stmts. The error occurs when LTRANS is streaming callgraph edges back in. The LTO format uses stmt uids to associate call stmts with callgraph edges between WPA and LTRANS. For example, in lto-cgraph.c, lto_output_edge writes out the gimple_uid, and input_edge reads it back in. lto_prepare_function_for_streaming has code to renumber the stmt UIDs when the code is streamed back out, but for some reason this isn't called for clones: 307 /* Do body modifications needed for streaming before we fork out 308 worker processes. */ 309 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 310 if (!node->clone_of && gimple_has_body_p (node->decl)) 311 lto_prepare_function_for_streaming (node); Hence the combination of -fanalyzer and -flto will fail in LTRANS's stream-in if any function clones are encountered. It's not fully clear to me why this isn't done for clones, and what the correct fix should be to allow arbitrary changes to uids within WPA passes. In the meantime, this patch works around the issue by updating the analyzer to save and restore the UIDs, fixing the error. gcc/analyzer/ChangeLog: PR analyzer/98599 * supergraph.cc (saved_uids::make_uid_unique): New. (saved_uids::restore_uids): New. (supergraph::supergraph): Replace assignments to stmt->uid with calls to m_stmt_uids.make_uid_unique. (supergraph::~supergraph): New. * supergraph.h (class saved_uids): New. (supergraph::~supergraph): New decl. (supergraph::m_stmt_uids): New field. gcc/testsuite/ChangeLog: PR analyzer/98599 * gcc.dg/analyzer/pr98599-a.c: New test. * gcc.dg/analyzer/pr98599-b.c: New test.
2021-04-11Daily bump.GCC Administrator1-0/+6
2021-04-10analyzer: fix ICE on assignment from STRING_CST when building path [PR100011]David Malcolm1-1/+1
gcc/analyzer/ChangeLog: PR analyzer/100011 * region-model.cc (region_model::on_assignment): Avoid NULL dereference if ctxt is NULL when assigning from a STRING_CST. gcc/testsuite/ChangeLog: PR analyzer/100011 * gcc.dg/analyzer/pr100011.c: New test.
2021-04-09Daily bump.GCC Administrator1-0/+94
2021-04-08analyzer: fix leak false +ves due to maybe-clobbered regions [PR99042,PR99774]David Malcolm10-73/+309
Prior to this patch, program_state::detect_leaks worked by finding all live svalues in the old state and in the new state, and calling on_svalue_leak for each svalue that has changed from being live to not being live. PR analyzer/99042 and PR analyzer/99774 both describe false leak diagnostics from -fanalyzer (a false FILE * leak in git, and a false malloc leak in qemu, respectively). In both cases the root cause of the false leak diagnostic relates to svalues no longer being explicitly bound in the store due to regions being conservatively clobbered, due to an unknown function being called, or due to a write through a pointer that could alias the region, respectively. We have a transition from an svalue being explicitly live to not being explicitly live - but only because the store is being conservative, clobbering the binding. The leak detection is looking for transitions from "definitely live" to "not definitely live", when it should be looking for transitions from "definitely live" to "definitely not live". This patch introduces a new class to temporarily capture information about svalues that were explicitly live, but for which a region bound to them got clobbered for conservative reasons. This new "uncertainty_t" class is passed around to capture the data long enough for use in program_state::detect_leaks, where it is used to only complain about svalues that were definitely live and are now both not definitely live *or* possibly-live i.e. definitely not-live. The class also captures for which svalues we can't meaningfully track sm-state anymore, and resets the svalues back to the "start" state. Together, these changes fix the false leak reports. gcc/analyzer/ChangeLog: PR analyzer/99042 PR analyzer/99774 * engine.cc (impl_region_model_context::impl_region_model_context): Add uncertainty param and use it to initialize m_uncertainty. (impl_region_model_context::get_uncertainty): New. (impl_sm_context::get_fndecl_for_call): Add NULL for new uncertainty param when constructing impl_region_model_context. (impl_sm_context::get_state): Likewise. (impl_sm_context::set_next_state): Likewise. (impl_sm_context::warn): Likewise. (exploded_node::on_stmt): Add uncertainty param and use it when constructing impl_region_model_context. (exploded_node::on_edge): Add uncertainty param and pass to on_edge call. (exploded_node::detect_leaks): Create uncertainty_t and pass to impl_region_model_context. (exploded_graph::get_or_create_node): Create uncertainty_t and pass to prune_for_point. (maybe_process_run_of_before_supernode_enodes): Create uncertainty_t and pass to impl_region_model_context. (exploded_graph::process_node): Create uncertainty_t instances and pass around as needed. * exploded-graph.h (impl_region_model_context::impl_region_model_context): Add uncertainty param. (impl_region_model_context::get_uncertainty): New decl. (impl_region_model_context::m_uncertainty): New field. (exploded_node::on_stmt): Add uncertainty param. (exploded_node::on_edge): Likewise. * program-state.cc (sm_state_map::on_liveness_change): Get uncertainty from context and use it to unset sm-state from svalues as appropriate. (program_state::on_edge): Add uncertainty param and use it when constructing impl_region_model_context. Fix indentation. (program_state::prune_for_point): Add uncertainty param and use it when constructing impl_region_model_context. (program_state::detect_leaks): Get any uncertainty from ctxt and use it to get maybe-live svalues for dest_state, rather than definitely-live ones; use this when determining which svalues have leaked. (selftest::test_program_state_merging): Create uncertainty_t and pass to impl_region_model_context. * program-state.h (program_state::on_edge): Add uncertainty param. (program_state::prune_for_point): Likewise. * region-model-impl-calls.cc (call_details::get_uncertainty): New. (region_model::impl_call_memcpy): Pass uncertainty to mark_region_as_unknown call. (region_model::impl_call_memset): Likewise. (region_model::impl_call_strcpy): Likewise. * region-model-reachability.cc (reachable_regions::handle_sval): Also add sval to m_mutable_svals. * region-model.cc (region_model::on_assignment): Pass any uncertainty from ctxt to the store::set_value call. (region_model::handle_unrecognized_call): Get any uncertainty from ctxt and use it to record mutable svalues at the unknown call. (region_model::get_reachable_svalues): Add uncertainty param and use it to mark any maybe-bound svalues as being reachable. (region_model::set_value): Pass any uncertainty from ctxt to the store::set_value call. (region_model::mark_region_as_unknown): Add uncertainty param and pass it on to the store::mark_region_as_unknown call. (region_model::update_for_call_summary): Add uncertainty param and pass it on to the region_model::mark_region_as_unknown call. * region-model.h (call_details::get_uncertainty): New decl. (region_model::get_reachable_svalues): Add uncertainty param. (region_model::mark_region_as_unknown): Add uncertainty param. (region_model_context::get_uncertainty): New vfunc. (noop_region_model_context::get_uncertainty): New vfunc implementation. * store.cc (dump_svalue_set): New. (uncertainty_t::dump_to_pp): New. (uncertainty_t::dump): New. (binding_cluster::clobber_region): Pass NULL for uncertainty to remove_overlapping_bindings. (binding_cluster::mark_region_as_unknown): Add uncertainty param and pass it to remove_overlapping_bindings. (binding_cluster::remove_overlapping_bindings): Add uncertainty param. Use it to record any svalues that were in clobbered bindings. (store::set_value): Add uncertainty param. Pass it to binding_cluster::mark_region_as_unknown when handling symbolic regions. (store::mark_region_as_unknown): Add uncertainty param and pass it to binding_cluster::mark_region_as_unknown. (store::remove_overlapping_bindings): Add uncertainty param and pass it to binding_cluster::remove_overlapping_bindings. * store.h (binding_cluster::mark_region_as_unknown): Add uncertainty param. (binding_cluster::remove_overlapping_bindings): Likewise. (store::set_value): Likewise. (store::mark_region_as_unknown): Likewise. gcc/testsuite/ChangeLog: PR analyzer/99042 PR analyzer/99774 * gcc.dg/analyzer/pr99042.c: New test. * gcc.dg/analyzer/pr99774-1.c: New test. * gcc.dg/analyzer/pr99774-2.c: New test.
2021-04-06Daily bump.GCC Administrator1-0/+18
2021-04-05analyzer: fix ICE on zero-arg calls passed to __attribute__((nonnull)) [PR ↵David Malcolm2-2/+3
99906] gcc/analyzer/ChangeLog: PR analyzer/99906 * analyzer.cc (maybe_reconstruct_from_def_stmt): Fix NULL dereference on calls with zero arguments. * sm-malloc.cc (malloc_state_machine::on_stmt): When handling __attribute__((nonnull)), only call get_diagnostic_tree if the result will be used. gcc/testsuite/ChangeLog: PR analyzer/99906 * gcc.dg/analyzer/pr99906.c: New test.
2021-04-05analyzer: fix apparent hang with -fanalyzer-verbosity=0 [PR analyzer/99886]David Malcolm1-3/+5
The analyzer appeared to enter an infinite loop on malloc-1.c when -fanalyzer-verbosity=0 was used. In fact, it was slowly counting from 0 to 0xffffffff. Root cause is looping up to effectively ((unsigned)0) - 1 in diagnostic_manager::consolidate_conditions when there are no events in the path. Fixed by the following, which uses signed integers when subtracting from path->num_events () when simplifying checker_paths. gcc/analyzer/ChangeLog: PR analyzer/99886 * diagnostic-manager.cc (diagnostic_manager::prune_interproc_events): Use signed integers when subtracting one from path->num_events (). (diagnostic_manager::consolidate_conditions): Likewise. Convert next_idx to a signed int. gcc/testsuite/ChangeLog: PR analyzer/99886 * gcc.dg/analyzer/pr99886.c: New test.
2021-04-02Daily bump.GCC Administrator1-0/+56
2021-04-01analyzer: record per-enode saved_diagnosticsDavid Malcolm7-55/+65
Various places iterate through all of the saved_diagnostics to find just the ones that are at a given enode. This patch adds a per-enode record of the diagnostics that are at each node, to save iterating through all of the diagnostics each time. gcc/analyzer/ChangeLog: * diagnostic-manager.cc (diagnostic_manager::add_diagnostic): Make enode param non-constant, and call add_diagnostic on it. Add enode index to log message. (diagnostic_manager::add_diagnostic): Make enode param non-constant. * diagnostic-manager.h (diagnostic_manager::add_diagnostic): Likewise for both decls. * engine.cc (impl_region_model_context::impl_region_model_context): Likewise for enode_for_diag. (impl_sm_context::impl_sm_context): Likewise. (impl_sm_context::m_enode_for_diag): Likewise. (exploded_node::dump_dot): Don't pass the diagnostic manager to dump_saved_diagnostics. (exploded_node::dump_saved_diagnostics): Drop param. Iterate directly through all saved diagnostics for the enode, rather than all saved diagnostics in the diagnostic_manager and filtering. (exploded_node::on_stmt): Make non-const. (exploded_node::on_edge): Likewise. (exploded_node::on_longjmp): Likewise. (exploded_node::detect_leaks): Likewise. (exploded_graph::get_or_create_node): Make enode_for_diag param non-const. (exploded_graph_annotator::print_enode): Iterate directly through all saved diagnostics for the enode, rather than all saved diagnostics in the diagnostic_manager and filtering. * exploded-graph.h (impl_region_model_context::impl_region_model_context): Make enode_for_diag param non-constant. (impl_region_model_context::m_enode_for_diag): Likewise. (exploded_node::dump_saved_diagnostics): Drop param. (exploded_node::on_stmt): Make non-const. (exploded_node::on_edge): Likewise. (exploded_node::on_longjmp): Likewise. (exploded_node::detect_leaks): Likewise. (exploded_node::add_diagnostic): New. (exploded_node::get_num_diagnostics): New. (exploded_node::get_saved_diagnostic): New. (exploded_node::m_saved_diagnostics): New. (exploded_graph::get_or_create_node): Make enode_for_diag param non-constant. * feasible-graph.cc (feasible_node::dump_dot): Drop diagnostic_manager from call to dump_saved_diagnostics. * program-state.cc (program_state::on_edge): Convert enode param to non-const pointer. (program_state::prune_for_point): Likewise for enode_for_diag param. * program-state.h (program_state::on_edge): Convert enode param to non-const pointer. (program_state::prune_for_point): Likewise for enode_for_diag param.
2021-04-01Daily bump.GCC Administrator1-0/+16
2021-03-31analyzer: avoid printing '<unknown>' for SSA names [PR99771]David Malcolm5-8/+140
We don't want to print '<unknown>' in our diagnostics, but PR analyzer/99771 lists various cases where -fanalyzer does, due to using the SSA_NAME for a temporary when determining the best tree to use. This can happen in two ways: (a) ...when a better expression than the SSA_NAME could be built, but finding it requires traversing the relationships in the region_model in a graph-like way, rather than by considering individual svalues and regions. (b) ...when the only remaining user of the underlying svalue is the SSA_NAME, typically due to the diagnostic referring to a temporary. I've been experimenting with fixing (a), but don't have a good fix yet. In the meantime, this patch addresses (b) by detecting if we have the SSA_NAME for a temporary, and, for the cases where it's possible, reconstructing a tree by walking the def-stmts. This fixes various cases of (b) and ameliorates some cases of (a). gcc/analyzer/ChangeLog: PR analyzer/99771 * analyzer.cc (maybe_reconstruct_from_def_stmt): New. (fixup_tree_for_diagnostic_1): New. (fixup_tree_for_diagnostic): New. * analyzer.h (fixup_tree_for_diagnostic): New decl. * checker-path.cc (call_event::get_desc): Call fixup_tree_for_diagnostic and use it for the call_with_state call. (warning_event::get_desc): Likewise for the final_event and make_label_text calls. * engine.cc (impl_region_model_context::on_state_leak): Likewise for the on_leak and add_diagnostic calls. * region-model.cc (region_model::get_representative_tree): Likewise for the result. gcc/testsuite/ChangeLog: PR analyzer/99771 * gcc.dg/analyzer/data-model-10.c: Update expected output. * gcc.dg/analyzer/malloc-ipa-13.c: Likewise. * gcc.dg/analyzer/malloc-ipa-13a.c: New test. * gcc.dg/analyzer/pr99771-1.c: New test.
2021-03-31Daily bump.GCC Administrator1-0/+16
2021-03-30analyzer: remove old decl of region::dump_to_ppDavid Malcolm1-5/+0
This was made redundant in the GCC 11 rewrite of state (808f4dfeb3a95f50f15e71148e5c1067f90a126d). gcc/analyzer/ChangeLog: * region.h (region::dump_to_pp): Remove old decl.
2021-03-30analyzer: only call get_diagnostic_tree when it's neededDavid Malcolm4-8/+16
impl_sm_context::get_diagnostic_tree could be expensive, and I find myself needing to put a breakpoint on it to debug PR analyzer/99771, so only call it if we're about to use the result. gcc/analyzer/ChangeLog: * sm-file.cc (fileptr_state_machine::on_stmt): Only call get_diagnostic_tree if the result will be used. * sm-malloc.cc (malloc_state_machine::on_stmt): Likewise. (malloc_state_machine::on_deallocator_call): Likewise. (malloc_state_machine::on_realloc_call): Likewise. (malloc_state_machine::on_realloc_call): Likewise. * sm-sensitive.cc (sensitive_state_machine::warn_for_any_exposure): Likewise. * sm-taint.cc (taint_state_machine::on_stmt): Likewise.
2021-03-26Daily bump.GCC Administrator1-0/+15
2021-03-24analyzer; reset sm-state for SSA names at def-stmts [PR93695,PR99044,PR99716]David Malcolm6-0/+126
Various false positives from -fanalyzer involve SSA names in loops, where sm-state associated with an SSA name from one iteration is erroneously reused in a subsequent iteration. For example, PR analyzer/99716 describes a false "double 'fclose' of FILE 'fp'" on: for (i = 0; i < 2; ++i) { FILE *fp = fopen ("/tmp/test", "w"); fprintf (fp, "hello"); fclose (fp); } where the gimple of the loop body is: fp_7 = fopen ("/tmp/test", "w"); __builtin_fwrite ("hello", 1, 5, fp_7); fclose (fp_7); i_10 = i_1 + 1; where fp_7 transitions to "closed" at the fclose, but is not reset at the subsequent fopen, leading to the false positive when the fclose is re-reached. The fix is to reset sm-state for svalues that involve an SSA name at the SSA name's def-stmt, since the def-stmt effectively changes the meaning of those related svalues. gcc/analyzer/ChangeLog: PR analyzer/93695 PR analyzer/99044 PR analyzer/99716 * engine.cc (exploded_node::on_stmt): Clear sm-state involving an SSA name at the def-stmt of that SSA name. * program-state.cc (sm_state_map::purge_state_involving): New. * program-state.h (sm_state_map::purge_state_involving): New decl. * region-model.cc (selftest::test_involves_p): New. (selftest::analyzer_region_model_cc_tests): Call it. * svalue.cc (class involvement_visitor): New class (svalue::involves_p): New. * svalue.h (svalue::involves_p): New decl. gcc/testsuite/ChangeLog: PR analyzer/93695 PR analyzer/99044 PR analyzer/99716 * gcc.dg/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c: Remove xfail. * gcc.dg/analyzer/pr93695-1.c: New test. * gcc.dg/analyzer/pr99044-1.c: New test. * gcc.dg/analyzer/pr99044-2.c: New test. * gcc.dg/analyzer/pr99716-1.c: New test. * gcc.dg/analyzer/pr99716-2.c: New test. * gcc.dg/analyzer/pr99716-3.c: New test.
2021-03-20Daily bump.GCC Administrator1-0/+6
2021-03-19analyzer: mark epath_finder with DISABLE_COPY_AND_ASSIGN [PR99614]David Malcolm1-0/+2
cppcheck warns that class epath_finder does dynamic memory allocation, but is missing a copy constructor and operator=. This class isn't meant to be copied or assigned, so mark it with DISABLE_COPY_AND_ASSIGN. gcc/analyzer/ChangeLog: PR analyzer/99614 * diagnostic-manager.cc (class epath_finder): Add DISABLE_COPY_AND_ASSIGN.
2021-03-16Daily bump.GCC Administrator1-0/+4
2021-03-15analyzer: fix missing comma in initializerMartin Liska1-1/+1
Fixes the following valid warning: gcc/analyzer/sm-file.cc:250:5: warning: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Wstring-concatenation] gcc/analyzer/ChangeLog: * sm-file.cc (get_file_using_fns): Add missing comma in initializer.