aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/kf.cc
AgeCommit message (Collapse)AuthorFilesLines
2024-10-24analyzer: avoid implicit use of global_dc's pretty_printer [PR116613]David Malcolm1-57/+61
Previously, various places in the analyzer generated message strings by cloning the diagnostic_context's pretty_printer, printing to that pretty_printer's buffer, and then returning a copy of the buffer contents. This implicit use of a particular pretty printer doesn't work well for the "multiple diagnostic output formats" case (PR other/116613), such as differences in colorization, or in how phase 3 of formatting works. Hence as enabling work towards that, the following patch reworks the various functions returning a label_text string in favor of functions that print to a specific pretty_printer, such as diagnotic_event's "get_desc" vfunc, which becomes "print_desc". This makes the particular pretty_printer in use explicit in each case. Previously, the various pending_diagnostic::describe_* vfuncs returned a label_text, with the return of an empty string signifying that no description could be generated. With this patch, these vfuncs gain a "pretty_printer &" param and a bool return value and now either print to the pretty_printer and return true, or return false to signify the "no description available" case. No functional change intended. gcc/analyzer/ChangeLog: PR other/116613 * bounds-checking.cc (concrete_buffer_overflow::describe_final_event): Convert return type from label_text to bool. Add "pp" param and either print to it and return true, or return false. (concrete_buffer_overflow::describe_final_event_as_bytes): Convert to print to a pp rather than returning a label_text. (concrete_buffer_overflow::describe_final_event_as_bits): Likewise. (class concrete_buffer_over_read): Analogous changes to above. (class concrete_buffer_underwrite): Likewise. (class concrete_buffer_under_read): Likewise. (class symbolic_buffer_overflow): Likewise. (class symbolic_buffer_over_read): Likewise. * call-details.cc (class overlapping_buffers): Likewise. * call-info.cc (call_info::print): Reimplement. (class call_info::add_events_to_path::call_event): Convert "get_desc" vfunc to "print_desc", dropping return type, adding "pp" param, and printing to it. (class succeed_or_fail_call_info): Likewise. * call-info.h (class call_info): Likewise. (class succeed_or_fail_call_info): Likewise. * checker-event.cc (checker_event::dump): Reimplement. (checker_event::prepare_for_emission): Update for change from get_desc to print_desc. (debug_event::get_desc): Convert to... (debug_event::print_desc): ...this. (precanned_custom_event::get_desc): Convert to... (precanned_custom_event::print_desc): ...this. (statement_event::get_desc): Convert to... (statement_event::print_desc): ...this. (region_creation_event_memory_space::get_desc): Convert to... (region_creation_event_memory_space::print_desc): ...this. (region_creation_event_capacity::get_desc): Convert to... (region_creation_event_capacity::print_desc): ...this. (region_creation_event_allocation_size::get_desc): Convert to... (region_creation_event_allocation_size::print_desc): ...this. (region_creation_event_debug::get_desc): Convert to... (region_creation_event_debug::print_desc): ...this. (function_entry_event::get_desc): Convert to... (function_entry_event::print_desc): ...this. (state_change_event::get_desc): Convert to... (state_change_event::print_desc): ...this. (state_change_event::get_meaning): Update for change to pending_diagnostic::get_meaning_for_state_change. (superedge_event::should_filter_p): Convert from usage of get_desc to print_desc. (start_cfg_edge_event::get_desc): Convert to... (start_cfg_edge_event::print_desc): ...this. (call_event::get_desc): Convert to... (call_event::print_desc): ...this. (return_event::get_desc): Convert to... (return_event::print_desc): ...this. (start_consolidated_cfg_edges_event::get_desc): Convert to... (start_consolidated_cfg_edges_event::print_desc): ...this. (inlined_call_event::get_desc): Convert to... (inlined_call_event::print_desc): ...this. (setjmp_event::get_desc): Convert to... (setjmp_event::print_desc): ...this. (rewind_from_longjmp_event::get_desc): Convert to... (rewind_from_longjmp_event::print_desc): ...this. (rewind_to_setjmp_event::get_desc): Convert to... (rewind_to_setjmp_event::print_desc): ...this. (warning_event::get_desc): Convert to... (warning_event::print_desc): ...this. * checker-event.h: Convert the various "get_desc" vfunc decls to "print_desc". * checker-path.cc (checker_path::dump): Convert to usage of checker_event::print_desc. (checker_path::debug): Convert to debug form of checker_event::get_desc. * diagnostic-manager.cc (diagnostic_manager::prune_interproc_events): Likewise. (diagnostic_manager::prune_system_headers): Likewise. * engine.cc (call_summary_edge_info::get_desc): Convert to... (call_summary_edge_info::print_desc): ...this. (stale_jmp_buf::describe_final_event): Update for change to this vfunc. (tainted_args_function_custom_event::get_desc): Convert to... (tainted_args_function_custom_event::print_desc): ...this. (tainted_args_field_custom_event::get_desc): Convert to... (tainted_args_field_custom_event::print_desc): ...this. (tainted_args_callback_custom_event::get_desc): Convert to... (tainted_args_callback_custom_event::print_desc): ...this. (jump_through_null::describe_final_event): Update for change to this vfunc. * infinite-loop.cc (perpetual_start_cfg_edge_event::get_desc): Convert to... (perpetual_start_cfg_edge_event::print_desc): ...this. (looping_back_event::get_desc): Convert to... (looping_back_event::print_desc): ...this. (looping_back_event::describe_final_event): Update for change to this vfunc. * infinite-recursion.cc (class infinite_recursion_diagnostic): Update for changes to pending_diagnostic. * kf.cc (class putenv_of_auto_var): Likewise. (kf_realloc::impl_call_post): Update for changes to call_info. (kf_strchr::impl_call_post): Likewise. (kf_strncpy::impl_call_post): Likewise. (kf_strstr::impl_call_post): Likewise. (class kf_strtok::undefined_behavior): Update for changes to pending_diagnostic. (class strtok_call_info): Update for changes to call_info. * pending-diagnostic.cc (evdesc::event_desc::formatted_print): Delete. * pending-diagnostic.h (struct event_desc): Delete. (struct state_change): Drop event_desc base class. (struct call_with_state): Likewise. (struct return_of_state): Likewise. (struct final_event): Likewise. (pending_event::describe_state_change): Convert return type from label_text to bool. Add "pp" param and either print to it and return true, or return false. Do the latter for the base class implementation. (pending_event::describe_call_with_state): Likewise. (pending_event::describe_return_of_state): Likewise. (pending_event::describe_final_event): Likewise. * region-model.cc (poisoned_value_diagnostic::describe_final_event): Update for change to this vfunc. (shift_count_negative_diagnostic::describe_final_event): Likewise. (shift_count_overflow_diagnostic::describe_final_event): Likewise. (ptrdiff_region_creation_event::get_desc): Convert to... (ptrdiff_region_creation_event::print_desc): ...this. (undefined_ptrdiff_diagnostic::describe_final_event): Update for change to this vfunc. (write_to_const_diagnostic::describe_final_event): Likewise. (write_to_string_literal_diagnostic::describe_final_event): Likewise. (dubious_allocation_size::describe_final_event): Likewise. (null_terminator_check_event::get_desc): Convert to... (null_terminator_check_event::print_desc): ...this. (float_as_size_arg::describe_final_event): Update for change to this vfunc. (exposure_through_uninit_copy::describe_final_event): Likewise. * sm-fd.cc: Include "diagnostic-core.h". Update throughout for changes to pending_diagnostic vfuncs. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * varargs.cc: Likewise. gcc/ChangeLog: PR other/116613 * diagnostic-format-json.cc (make_json_for_path): Add "ref_pp" param and use when obtaining event descriptions. (json_output_format::on_report_diagnostic): Pass this format's printer as the above. * diagnostic-format-sarif.cc (sarif_builder::make_location_object): Clone this format's printer and use it to obtain the text of the message. * diagnostic-path.cc: Include "pretty-print-markup.h". (diagnostic_event::get_desc): New. (path_label::get_text): Update for changes to diagnostic_event. (event_range::print): Likewise. (class element_event_desc): New. (diagnostic_text_output_format::print_path): Update for changes to diagnostic_event. * diagnostic-path.h (diagnostic_event::get_desc): Replace with... (diagnostic_event::print_desc): ...this. (diagnostic_event::get_desc): Add this back for debugging, without the bool param. * pretty-print.cc (pp_printf_n): New. * pretty-print.h (pp_printf_n): New decl. * selftest-diagnostic-path.h (test_diagnostic_event::get_desc): Convert to... (test_diagnostic_event::print_desc): ...this. * simple-diagnostic-path.cc (simple_diagnostic_event::print_desc): New. (selftest::test_intraprocedural_path): Use debug form of get_desc. * simple-diagnostic-path.h (simple_diagnostic_event::get_desc): Convert to... (simple_diagnostic_event::print_desc): ...this, moving implementation to test_diagnostic_event. gcc/testsuite/ChangeLog: PR other/116613 * gcc.dg/plugin/analyzer_cpython_plugin.c: Convert call outcomes from "get_desc" to print_desc". * gcc.dg/plugin/analyzer_gil_plugin.c: Update for changes to pending_diagnostic vfuncs. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-07-04analyzer: handle <error.h> at -O0 [PR115724]David Malcolm1-0/+4
At -O0, glibc's: __extern_always_inline void error (int __status, int __errnum, const char *__format, ...) { if (__builtin_constant_p (__status) && __status != 0) __error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack ()); else __error_alias (__status, __errnum, __format, __builtin_va_arg_pack ()); } becomes just: __extern_always_inline void error (int __status, int __errnum, const char *__format, ...) { if (0) __error_noreturn (__status, __errnum, __format, __builtin_va_arg_pack ()); else __error_alias (__status, __errnum, __format, __builtin_va_arg_pack ()); } and thus calls to "error" are calls to "__error_alias" by the time -fanalyzer "sees" them. Handle them with more special-casing in kf.cc. gcc/analyzer/ChangeLog: PR analyzer/115724 * kf.cc (register_known_functions): Add __error_alias and __error_at_line_alias. gcc/testsuite/ChangeLog: PR analyzer/115724 * c-c++-common/analyzer/error-pr115724.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-05-30Add new text_art::tree_widget and use it in analyzerDavid Malcolm1-0/+1
This patch adds a new text_art::tree_widget, which makes it easy to generate hierarchical visualizations using either ASCII: +- Child 0 | +- Grandchild 0 0 | +- Grandchild 0 1 | `- Grandchild 0 2 +- Child 1 | +- Grandchild 1 0 | +- Grandchild 1 1 | `- Grandchild 1 2 `- Child 2 +- Grandchild 2 0 +- Grandchild 2 1 `- Grandchild 2 2 or Unicode: Root ├─ Child 0 │ ├─ Grandchild 0 0 │ ├─ Grandchild 0 1 │ ╰─ Grandchild 0 2 ├─ Child 1 │ ├─ Grandchild 1 0 │ ├─ Grandchild 1 1 │ ╰─ Grandchild 1 2 ╰─ Child 2 ├─ Grandchild 2 0 ├─ Grandchild 2 1 ╰─ Grandchild 2 2 potentially with colorization of the connecting lines. It adds a new template for typename T: void text_art::dump<T> (const T&); for using this to dump any object to stderr that supports a make_dump_widget method, with similar templates for dumping to a pretty_printer * and a FILE *. It uses this within the analyzer to add two new families of dumping methods: one for program states, e.g.: (gdb) call state->dump() State ├─ Region Model │ ├─ Current Frame: frame: ‘calls_malloc’@2 │ ├─ Store │ │ ├─ m_called_unknown_fn: false │ │ ├─ frame: ‘test’@1 │ │ │ ╰─ _1: (INIT_VAL(n_2(D))*(size_t)4) │ │ ╰─ frame: ‘calls_malloc’@2 │ │ ├─ result_4: &HEAP_ALLOCATED_REGION(27) │ │ ╰─ _5: &HEAP_ALLOCATED_REGION(27) │ ╰─ Dynamic Extents │ ╰─ HEAP_ALLOCATED_REGION(27): (INIT_VAL(n_2(D))*(size_t)4) ╰─ ‘malloc’ state machine ╰─ 0x468cb40: &HEAP_ALLOCATED_REGION(27): unchecked ({free}) (‘result_4’) and the other for showing the detail of the recursive makeup of svalues and regions, e.g. the (INIT_VAL(n_2(D))*(size_t)4) from above: (gdb) call size_in_bytes->dump() (17): ‘long unsigned int’: binop_svalue(mult_expr: ‘*’) ├─ (15): ‘size_t’: initial_svalue │ ╰─ m_reg: (12): ‘size_t’: decl_region(‘n_2(D)’) │ ╰─ parent: (9): frame_region(‘test’, index: 0, depth: 1) │ ╰─ parent: (1): stack region │ ╰─ parent: (0): root region ╰─ (16): ‘size_t’: constant_svalue (‘4’) I've already found both of these useful when debugging analyzer issues. The patch uses the former to update the output of -fdump-analyzer-exploded-nodes-2 and -fdump-analyzer-exploded-nodes-3. The older dumping functions within the analyzer are retained in case they turn out to still be useful for debugging. gcc/ChangeLog: * Makefile.in (OBJS-libcommon): Add text-art/tree-widget.o. * doc/analyzer.texi: Rewrite discussion of dumping state to cover the text_art::tree_widget-based dumps, with a more interesting example. * text-art/dump-widget-info.h: New file. * text-art/dump.h: New file. * text-art/selftests.cc (selftest::text_art_tests): Call text_art_tree_widget_cc_tests. * text-art/selftests.h (selftest::text_art_tree_widget_cc_tests): New decl. * text-art/theme.cc (ascii_theme::get_cppchar): Handle the various cell_kind::TREE_*. (unicode_theme::get_cppchar): Likewise. * text-art/theme.h (enum class theme::cell_kind): Add TREE_CHILD_NON_FINAL, TREE_CHILD_FINAL, TREE_X_CONNECTOR, and TREE_Y_CONNECTOR. * text-art/tree-widget.cc: New file. gcc/analyzer/ChangeLog: * call-details.cc: Define INCLUDE_VECTOR. * call-info.cc: Likewise. * call-summary.cc: Likewise. * checker-event.cc: Likewise. * checker-path.cc: Likewise. * complexity.cc: Likewise. * constraint-manager.cc: Likewise. (bounded_range::make_dump_widget): New. (bounded_ranges::add_to_dump_widget): New. (equiv_class::make_dump_widget): New. (constraint::make_dump_widget): New. (bounded_ranges_constraint::make_dump_widget): New. (constraint_manager::make_dump_widget): New. * constraint-manager.h (bounded_range::make_dump_widget): New decl. (bounded_ranges::add_to_dump_widget): New decl. (equiv_class::make_dump_widget): New decl. (constraint::make_dump_widget): New decl. (bounded_ranges_constraint::make_dump_widget): New decl. (constraint_manager::make_dump_widget): New decl. * diagnostic-manager.cc: Define INCLUDE_VECTOR. * engine.cc: Likewise. Include "text-art/dump.h". (setjmp_svalue::print_dump_widget_label): New. (setjmp_svalue::add_dump_widget_children): New. (exploded_graph::dump_exploded_nodes): Use text_art::dump_to_file for -fdump-analyzer-exploded-nodes-2 and -fdump-analyzer-exploded-nodes-3. Fix overlong line. * feasible-graph.cc: Define INCLUDE_VECTOR. * infinite-recursion.cc: Likewise. * kf-analyzer.cc: Likewise. * kf-lang-cp.cc: Likewise. * kf.cc: Likewise. * known-function-manager.cc: Likewise. * pending-diagnostic.cc: Likewise. * program-point.cc: Likewise. * program-state.cc: Likewise. Include "text-art/tree-widget" and "text-art/dump.h". (sm_state_map::make_dump_widget): New. (program_state::dump): New. (program_state::make_dump_widget): New. * program-state.h: Include "text-art/widget.h". (sm_state_map::make_dump_widget): New decl. (program_state::dump): New decl. (program_state::make_dump_widget): New decl. * ranges.cc: Define INCLUDE_VECTOR. * record-layout.cc: Likewise. * region-model-asm.cc: Likewise. * region-model-manager.cc: Likewise. * region-model-reachability.cc: Likewise. * region-model.cc: Likewise. Include "text-art/tree-widget.h". (region_to_value_map::make_dump_widget): New. (region_model::dump): New. (region_model::make_dump_widget): New. (selftest::test_dump): Add test of dump_to_pp<region_model>. * region-model.h: Include "text-art/widget.h" and "text-art/dump.h". (region_to_value_map::make_dump_widget): New decl. (region_model::dump): New decl. (region_model::make_dump_widget): New decl. * region.cc: Define INCLUDE_VECTOR and include "text-art/dump.h". (region::dump): New. (region::make_dump_widget): New. (region::add_dump_widget_children): New. (frame_region::print_dump_widget_label): New. (globals_region::print_dump_widget_label): New. (code_region::print_dump_widget_label): New. (function_region::print_dump_widget_label): New. (label_region::print_dump_widget_label): New. (stack_region::print_dump_widget_label): New. (heap_region::print_dump_widget_label): New. (root_region::print_dump_widget_label): New. (thread_local_region::print_dump_widget_label): New. (symbolic_region::print_dump_widget_label): New. (symbolic_region::add_dump_widget_children): New. (decl_region::print_dump_widget_label): New. (field_region::print_dump_widget_label): New. (element_region::print_dump_widget_label): New. (element_region::add_dump_widget_children): New. (offset_region::print_dump_widget_label): New. (offset_region::add_dump_widget_children): New. (sized_region::print_dump_widget_label): New. (sized_region::add_dump_widget_children): New. (cast_region::print_dump_widget_label): New. (cast_region::add_dump_widget_children): New. (heap_allocated_region::print_dump_widget_label): New. (alloca_region::print_dump_widget_label): New. (string_region::print_dump_widget_label): New. (bit_range_region::print_dump_widget_label): New. (var_arg_region::print_dump_widget_label): New. (errno_region::print_dump_widget_label): New. (private_region::print_dump_widget_label): New. (unknown_region::print_dump_widget_label): New. * region.h: Include "text-art/widget.h". (region::dump): New decl. (region::make_dump_widget): New decl. (region::add_dump_widget_children): New decl. (frame_region::print_dump_widget_label): New decl. (globals_region::print_dump_widget_label): New decl. (code_region::print_dump_widget_label): New decl. (function_region::print_dump_widget_label): New decl. (label_region::print_dump_widget_label): New decl. (stack_region::print_dump_widget_label): New decl. (heap_region::print_dump_widget_label): New decl. (root_region::print_dump_widget_label): New decl. (thread_local_region::print_dump_widget_label): New decl. (symbolic_region::print_dump_widget_label): New decl. (symbolic_region::add_dump_widget_children): New decl. (decl_region::print_dump_widget_label): New decl. (field_region::print_dump_widget_label): New decl. (element_region::print_dump_widget_label): New decl. (element_region::add_dump_widget_children): New decl. (offset_region::print_dump_widget_label): New decl. (offset_region::add_dump_widget_children): New decl. (sized_region::print_dump_widget_label): New decl. (sized_region::add_dump_widget_children): New decl. (cast_region::print_dump_widget_label): New decl. (cast_region::add_dump_widget_children): New decl. (heap_allocated_region::print_dump_widget_label): New decl. (alloca_region::print_dump_widget_label): New decl. (string_region::print_dump_widget_label): New decl. (bit_range_region::print_dump_widget_label): New decl. (var_arg_region::print_dump_widget_label): New decl. (errno_region::print_dump_widget_label): New decl. (private_region::print_dump_widget_label): New decl. (unknown_region::print_dump_widget_label): New decl. * sm-fd.cc: Define INCLUDE_VECTOR. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-pattern-test.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * sm.cc: Likewise. * state-purge.cc: Likewise. * store.cc: Likewise. Include "text-art/tree-widget.h". (add_binding_to_tree_widget): New. (binding_map::add_to_tree_widget): New. (binding_cluster::make_dump_widget): New. (store::make_dump_widget): New. * store.h: Include "text-art/tree-widget.h". (binding_map::add_to_tree_widget): New decl. (binding_cluster::make_dump_widget): New decl. (store::make_dump_widget): New decl. * svalue.cc: Define INCLUDE_VECTOR. Include "make-unique.h" and "text-art/dump.h". (svalue::dump): New. (svalue::make_dump_widget): New. (region_svalue::print_dump_widget_label): New. (region_svalue::add_dump_widget_children): New. (constant_svalue::print_dump_widget_label): New. (constant_svalue::add_dump_widget_children): New. (unknown_svalue::print_dump_widget_label): New. (unknown_svalue::add_dump_widget_children): New. (poisoned_svalue::print_dump_widget_label): New. (poisoned_svalue::add_dump_widget_children): New. (initial_svalue::print_dump_widget_label): New. (initial_svalue::add_dump_widget_children): New. (unaryop_svalue::print_dump_widget_label): New. (unaryop_svalue::add_dump_widget_children): New. (binop_svalue::print_dump_widget_label): New. (binop_svalue::add_dump_widget_children): New. (sub_svalue::print_dump_widget_label): New. (sub_svalue::add_dump_widget_children): New. (repeated_svalue::print_dump_widget_label): New. (repeated_svalue::add_dump_widget_children): New. (bits_within_svalue::print_dump_widget_label): New. (bits_within_svalue::add_dump_widget_children): New. (widening_svalue::print_dump_widget_label): New. (widening_svalue::add_dump_widget_children): New. (placeholder_svalue::print_dump_widget_label): New. (placeholder_svalue::add_dump_widget_children): New. (unmergeable_svalue::print_dump_widget_label): New. (unmergeable_svalue::add_dump_widget_children): New. (compound_svalue::print_dump_widget_label): New. (compound_svalue::add_dump_widget_children): New. (conjured_svalue::print_dump_widget_label): New. (conjured_svalue::add_dump_widget_children): New. (asm_output_svalue::print_dump_widget_label): New. (asm_output_svalue::add_dump_widget_children): New. (const_fn_result_svalue::print_dump_widget_label): New. (const_fn_result_svalue::add_dump_widget_children): New. * svalue.h: Include "text-art/widget.h". Add "using text_art::dump_widget_info". (svalue::dump): New decl. (svalue::make_dump_widget): New decl. (svalue::print_dump_widget_label): New decl. (svalue::print_dump_widget_label): New decl. (svalue::add_dump_widget_children): New decl. (region_svalue::print_dump_widget_label): New decl. (region_svalue::add_dump_widget_children): New decl. (constant_svalue::print_dump_widget_label): New decl. (constant_svalue::add_dump_widget_children): New decl. (unknown_svalue::print_dump_widget_label): New decl. (unknown_svalue::add_dump_widget_children): New decl. (poisoned_svalue::print_dump_widget_label): New decl. (poisoned_svalue::add_dump_widget_children): New decl. (initial_svalue::print_dump_widget_label): New decl. (initial_svalue::add_dump_widget_children): New decl. (unaryop_svalue::print_dump_widget_label): New decl. (unaryop_svalue::add_dump_widget_children): New decl. (binop_svalue::print_dump_widget_label): New decl. (binop_svalue::add_dump_widget_children): New decl. (sub_svalue::print_dump_widget_label): New decl. (sub_svalue::add_dump_widget_children): New decl. (repeated_svalue::print_dump_widget_label): New decl. (repeated_svalue::add_dump_widget_children): New decl. (bits_within_svalue::print_dump_widget_label): New decl. (bits_within_svalue::add_dump_widget_children): New decl. (widening_svalue::print_dump_widget_label): New decl. (widening_svalue::add_dump_widget_children): New decl. (placeholder_svalue::print_dump_widget_label): New decl. (placeholder_svalue::add_dump_widget_children): New decl. (unmergeable_svalue::print_dump_widget_label): New decl. (unmergeable_svalue::add_dump_widget_children): New decl. (compound_svalue::print_dump_widget_label): New decl. (compound_svalue::add_dump_widget_children): New decl. (conjured_svalue::print_dump_widget_label): New decl. (conjured_svalue::add_dump_widget_children): New decl. (asm_output_svalue::print_dump_widget_label): New decl. (asm_output_svalue::add_dump_widget_children): New decl. (const_fn_result_svalue::print_dump_widget_label): New decl. (const_fn_result_svalue::add_dump_widget_children): New decl. * trimmed-graph.cc: Define INCLUDE_VECTOR. * varargs.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_cpython_plugin.c: Define INCLUDE_VECTOR. * gcc.dg/plugin/analyzer_gil_plugin.c: Likewise. * gcc.dg/plugin/analyzer_kernel_plugin.c: Likewise. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-05-03testsuite: fix analyzer C++ failures on Solaris [PR111475]David Malcolm1-0/+22
As part of PR analyzer/96395, these patches moved testcases from gcc.dg/analyzer to c-c++-common/analyzer: - r14-3503-g55f6a7d949abc7 - r14-3823-g50b5199cff6908 - r14-6564-gae034b9106fbdd Unfortunately this led to numerous g++ testsuite failures on Solaris, tracked as PR analyzer/111475. Almost all of the failures are due to standard library differences where including a C standard library on C++ e.g. <stdlib.h> leads to the plain symbols referencing the symbols "std::" via a "using" declaration, whereas I had written the code expecting them to use symbols in the root namespace. The analyzer has special-case handling of many functions by name. This patch generalizes such handling to also match against functions in "std::" for all of the cases I found in the testsuite (via manual inspection of the preprocessed test cases against Solaris headers). This fixes cases where the analyzer was failing to "know about" the behavior of such functions. Other such failures are due to "std::" prefixes appearing in names of functions in the output, leading to mismatches against expected output. The patch adds regexes to some cases, and moves some other cases back from c-c++-common to gcc.dg where the dg-multiline syntax isn't expressive enough. Various "fd-*.c" failures relate to Solaris's socket-handling functions not being marked with "noexcept", where due to PR analyzer/97111 we mishandle the exception-handling edges in the CFG, leading to leak false positives. The patch works around this by adding -fno-exceptions to these cases, pending a proper fix for PR analyzer/97111. gcc/analyzer/ChangeLog: PR analyzer/111475 * analyzer.cc (is_special_named_call_p): Add "look_in_std" param. (is_std_function_p): Make non-static. * analyzer.h (is_special_named_call_p): Add optional "look_in_std" param. (is_std_function_p): New decl. * engine.cc (stmt_requires_new_enode_p): Look for both "signal" and "std::signal". * kf.cc (register_known_functions): Add various "std::" copies of the known functions. * known-function-manager.cc (known_function_manager::~known_function_manager): Clean up m_std_ns_map_id_to_kf. (known_function_manager::add_std_ns): New. (known_function_manager::get_match): Also look for known "std::" functions. (known_function_manager::get_by_identifier_in_std_ns): New. * known-function-manager.h (known_function_manager::add_std_ns): New decl. (known_function_manager::get_by_identifier_in_std_ns): New decl. (known_function_manager::m_std_ns_map_id_to_kf): New field. * sm-file.cc (register_known_file_functions): Add various "std::" copies of the known functions. * sm-malloc.cc (malloc_state_machine::on_stmt): Handle "std::realloc". * sm-signal.cc (signal_unsafe_p): Consider "std::" copies of the functions as also being async-signal-unsafe. (signal_state_machine::on_stmt): Consider "std::signal". gcc/testsuite/ChangeLog: PR analyzer/111475 * c-c++-common/analyzer/fd-glibc-byte-stream-socket.c: Add -fno-exceptions for now. * c-c++-common/analyzer/fd-manpage-getaddrinfo-client.c: Likewise. * c-c++-common/analyzer/fd-mappage-getaddrinfo-server.c: Rename to... * c-c++-common/analyzer/fd-manpage-getaddrinfo-server.c: ...this, and add -fno-exceptions for now. * c-c++-common/analyzer/fd-socket-meaning.c: Add -fno-exceptions for now. * c-c++-common/analyzer/fd-symbolic-socket.c: Likewise. * c-c++-common/analyzer/flexible-array-member-1.c: Use regexp to handle C vs C++ differences in spelling of function name, which could have a "std::" prefix on some targets. * c-c++-common/analyzer/pr106539.c: Likewise. * c-c++-common/analyzer/malloc-ipa-8-unchecked.c: Move back to... * gcc.dg/analyzer/malloc-ipa-8-unchecked.c: ...here, dropping attempt to generalize output for C vs C++. * c-c++-common/analyzer/signal-4a.c: Move back to... * gcc.dg/analyzer/signal-4a.c: ...here, dropping attempt to generalize output for C vs C++. * c-c++-common/analyzer/signal-4b.c: Move back to... * gcc.dg/analyzer/signal-4b.c: ...here, dropping attempt to generalize output for C vs C++. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-03-23analyzer: fix ICE and false positive with -Wanalyzer-deref-before-check ↵David Malcolm1-0/+22
[PR114408] gcc/analyzer/ChangeLog: PR analyzer/114408 * engine.cc (impl_run_checkers): Free up any dominance info that we may have created. * kf.cc (class kf_ubsan_handler): New. (register_sanitizer_builtins): New. (register_known_functions): Call register_sanitizer_builtins. gcc/testsuite/ChangeLog: PR analyzer/114408 * c-c++-common/analyzer/deref-before-check-pr114408.c: New test. * c-c++-common/ubsan/analyzer-ice-pr114408.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-03-19analyzer: fixes to __atomic_{exchange,load,store} [PR114286]David Malcolm1-33/+102
In r14-1497-gef768035ae8090 I added some support to the analyzer for __atomic_ builtins (enough to fix false positives I was seeing in my integration tests). Unfortunately I messed up the implementation of __atomic_{exchange,load,store}, leading to ICEs seen in PR analyzer/114286. Fixed thusly, fixing the ICEs. Given that we're in stage 4, the patch doesn't add support for any of the various __atomic_compare_exchange builtins, so that these continue to fall back to the analyzer's "anything could happen" handling of unknown functions. Signed-off-by: David Malcolm <dmalcolm@redhat.com> gcc/analyzer/ChangeLog: PR analyzer/114286 * kf.cc (class kf_atomic_exchange): Reimplement based on signature seen in gimple, rather than user-facing signature. (class kf_atomic_load): Likewise. (class kf_atomic_store): New. (register_atomic_builtins): Register kf_atomic_store. gcc/testsuite/ChangeLog: PR analyzer/114286 * c-c++-common/analyzer/atomic-builtins-pr114286.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-01-03Update copyright years.Jakub Jelinek1-1/+1
2023-12-01diagnostics, analyzer: add optional per-diagnostic property bags to SARIFDavid Malcolm1-19/+13
I've found it useful in debugging the analyzer for the SARIF output to contain extra analyzer-specific data in each diagnostic. This patch: * adds a way for a diagnostic_metadata to populate a property bag within a SARIF "result" object based on a new vfunc * reworks how diagnostics are emitted within the analyzer so that a custom diagnostic_metadata subclass is used, which populates the property bag with information from the saved_diagnostic, and with a vfunc hook allowing for per-pending_diagnotic-subclass extra properties. Doing so makes it trivial to go from the SARIF output back to pertinent parts of the analyzer's internals (e.g. the index of the diagnostic within the ana::diagnostic_manager, the index of the ana::exploded_node, etc). It also replaces a lot of boilerplate in the "emit" implementations in the various pending_diagnostics subclasses. In particular, doing so fixes missing CVE metadata for -Wanalyzer-fd-phase-mismatch (where sm-fd.cc's fd_phase_mismatch::emit was failing to use its diagnostic_metadata instance). gcc/analyzer/ChangeLog: * analyzer.h (class saved_diagnostic): New forward decl. * bounds-checking.cc: Update for changes to pending_diagnostic::emit. * call-details.cc: Likewise. * diagnostic-manager.cc: Include "diagnostic-format-sarif.h". (saved_diagnostic::maybe_add_sarif_properties): New. (class pending_diagnostic_metadata): New. (diagnostic_manager::emit_saved_diagnostic): Create a pending_diagnostic_metadata and a diagnostic_emission_context. Pass the latter to the pending_diagnostic::emit vfunc. * diagnostic-manager.h (saved_diagnostic::maybe_add_sarif_properties): New decl. * engine.cc: Update for changes to pending_diagnostic::emit. * infinite-loop.cc: Likewise. * infinite-recursion.cc: Likewise. * kf-analyzer.cc: Likewise. * kf.cc: Likewise. * pending-diagnostic.cc (diagnostic_emission_context::get_pending_diagnostic): New. (diagnostic_emission_context::warn): New. (diagnostic_emission_context::inform): New. * pending-diagnostic.h (class diagnostic_emission_context): New. (pending_diagnostic::emit): Update params. (pending_diagnostic::maybe_add_sarif_properties): New vfunc. * region.cc: Don't include "diagnostic-metadata.h". * region-model.cc: Include "diagnostic-format-sarif.h". Update for changes to pending_diagnostic::emit. (exposure_through_uninit_copy::maybe_add_sarif_properties): New. * sm-fd.cc: Update for changes to pending_diagnostic::emit. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-pattern-test.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * store.cc: Don't include "diagnostic-metadata.h". * varargs.cc: Update for changes to pending_diagnostic::emit. gcc/ChangeLog: * diagnostic-core.h (emit_diagnostic_valist): New overload decl. * diagnostic-format-sarif.cc (sarif_builder::make_result_object): When we have metadata, call its maybe_add_sarif_properties vfunc. * diagnostic-metadata.h (class sarif_object): Forward decl. (diagnostic_metadata::~diagnostic_metadata): New. (diagnostic_metadata::maybe_add_sarif_properties): New vfunc. * diagnostic.cc (emit_diagnostic_valist): New overload. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fd-accept.c: Update for fix to missing CWE metadata for -Wanalyzer-fd-phase-mismatch. * gcc.dg/analyzer/fd-bind.c: Likewise. * gcc.dg/analyzer/fd-socket-misuse.c: Likewise. * gcc.dg/plugin/analyzer_cpython_plugin.c: Update for changes to pending_diagnostic::emit. * gcc.dg/plugin/analyzer_gil_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-11-18analyzer: new warning: -Wanalyzer-undefined-behavior-strtok [PR107573]David Malcolm1-1/+319
This patch: - adds support to the analyzer for tracking API-private state or which we don't have a decl (such as strtok's internal state), - uses it to implement a new -Wanalyzer-undefined-behavior-strtok which warns when strtok (NULL, delim) is called as the first call to strtok after main. gcc/analyzer/ChangeLog: PR analyzer/107573 * analyzer.h (register_known_functions): Add region_model_manager param. * analyzer.opt (Wanalyzer-undefined-behavior-strtok): New. * call-summary.cc (call_summary_replay::convert_region_from_summary_1): Handle RK_PRIVATE. * engine.cc (impl_run_checkers): Pass model manager to register_known_functions. * kf.cc (class undefined_function_behavior): New. (class kf_strtok): New. (register_known_functions): Add region_model_manager param. Use it to register "strtok". * region-model-manager.cc (region_model_manager::get_or_create_conjured_svalue): Add "idx" param. * region-model-manager.h (region_model_manager::get_or_create_conjured_svalue): Add "idx" param. (region_model_manager::get_root_region): New accessor. * region-model.cc (region_model::scan_for_null_terminator): Handle "expr" being null. (region_model::get_representative_path_var_1): Handle RK_PRIVATE. * region-model.h (region_model::called_from_main_p): Make public. * region.cc (region::get_memory_space): Handle RK_PRIVATE. (region::can_have_initial_svalue_p): Handle MEMSPACE_PRIVATE. (private_region::dump_to_pp): New. * region.h (MEMSPACE_PRIVATE): New. (RK_PRIVATE): New. (class private_region): New. (is_a_helper <const private_region *>::test): New. * store.cc (store::replay_call_summary_cluster): Handle RK_PRIVATE. * svalue.h (struct conjured_svalue::key_t): Add "idx" param to ctor and "m_idx" field. (class conjured_svalue::conjured_svalue): Likewise. gcc/ChangeLog: PR analyzer/107573 * doc/invoke.texi: Add -Wanalyzer-undefined-behavior-strtok. gcc/testsuite/ChangeLog: PR analyzer/107573 * c-c++-common/analyzer/strtok-1.c: New test. * c-c++-common/analyzer/strtok-2.c: New test. * c-c++-common/analyzer/strtok-3.c: New test. * c-c++-common/analyzer/strtok-4.c: New test. * c-c++-common/analyzer/strtok-cppreference.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-09-06analyzer: implement kf_strstr [PR105899]David Malcolm1-0/+96
gcc/analyzer/ChangeLog: PR analyzer/105899 * kf.cc (class kf_strstr): New. (kf_strstr::impl_call_post): New. (register_known_functions): Register it. gcc/testsuite/ChangeLog: PR analyzer/105899 * c-c++-common/analyzer/strstr-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-09-06analyzer: implement kf_strncpy [PR105899]David Malcolm1-0/+182
gcc/analyzer/ChangeLog: PR analyzer/105899 * kf.cc (class kf_strncpy): New. (kf_strncpy::impl_call_post): New. (register_known_functions): Register it. * region-model.cc (region_model::read_bytes): Handle unknown number of bytes. gcc/testsuite/ChangeLog: PR analyzer/105899 * c-c++-common/analyzer/null-terminated-strings-2.c: New test. * c-c++-common/analyzer/overlapping-buffers.c: Update dg-bogus directives to avoid clashing with note from <string.h> that might happen to have the same line number. Add strpncpy test coverage. * c-c++-common/analyzer/strncpy-1.c: New test. * gcc.dg/analyzer/null-terminated-strings-1.c (test_filled_nonzero): New. (void test_filled_zero): New. (test_filled_symbolic): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-09-06analyzer: add ctxt to fill_region/zero_fill_regionDavid Malcolm1-5/+2
I noticed that region_model's fill_region/zero_fill_region member functions weren't checking that the write to the region was valid. Fixed thusly. gcc/analyzer/ChangeLog: * kf.cc (kf_calloc::impl_call_pre): Pass ctxt to zero_fill_region. (kf_memset::impl_call_pre): Move responsibility for calling check_region_for_write to fill_region. * region-model.cc (region_model::on_assignment): Pass ctxt to zero_fill_region. (region_model::fill_region): Add "ctxt" param, using it to call check_region_for_write. (region_model::zero_fill_region): Likewise. * region-model.h (region_model::fill_region): Add "ctxt" param. (region_model::zero_fill_region): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_cpython_plugin.c: Pass ctxt to zero_fill_region. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-31Darwin: homogenize spelling of macOSFrancois-Xavier Coudert1-1/+1
gcc/ChangeLog: * config.in: Regenerate. * config/darwin-c.cc: Change spelling to macOS. * config/darwin-driver.cc: Likewise. * config/darwin.h: Likewise. * configure.ac: Likewise. * doc/contrib.texi: Likewise. * doc/extend.texi: Likewise. * doc/invoke.texi: Likewise. * doc/plugins.texi: Likewise. * doc/tm.texi: Regenerate. * doc/tm.texi.in: Change spelling to macOS. * plugin.cc: Likewise. gcc/analyzer/ChangeLog: * kf.cc: Change spelling to macOS. gcc/c-family/ChangeLog: * c.opt: Change spelling to macOS. gcc/fortran/ChangeLog: * gfortran.texi: Likewise. gcc/jit/ChangeLog: * jit-playback.cc: Change spelling to macOS. gcc/objc/ChangeLog: * objc-act.cc: Change spelling to macOS.
2023-08-29analyzer: new warning: -Wanalyzer-overlapping-buffers [PR99860]David Malcolm1-2/+17
gcc/ChangeLog: PR analyzer/99860 * Makefile.in (ANALYZER_OBJS): Add analyzer/ranges.o. gcc/analyzer/ChangeLog: PR analyzer/99860 * analyzer-selftests.cc (selftest::run_analyzer_selftests): Call selftest::analyzer_ranges_cc_tests. * analyzer-selftests.h (selftest::run_analyzer_selftests): New decl. * analyzer.opt (Wanalyzer-overlapping-buffers): New option. * call-details.cc: Include "analyzer/ranges.h" and "make-unique.h". (class overlapping_buffers): New. (call_details::complain_about_overlap): New. * call-details.h (call_details::complain_about_overlap): New decl. * kf.cc (kf_memcpy_memmove::impl_call_pre): Call cd.complain_about_overlap for memcpy and memcpy_chk. (kf_strcat::impl_call_pre): Call cd.complain_about_overlap. (kf_strcpy::impl_call_pre): Likewise. * ranges.cc: New file. * ranges.h: New file. gcc/ChangeLog: PR analyzer/99860 * doc/invoke.texi: Add -Wanalyzer-overlapping-buffers. gcc/testsuite/ChangeLog: PR analyzer/99860 * c-c++-common/analyzer/overlapping-buffers.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-29analyzer: improve strdup handling [PR105899]David Malcolm1-9/+19
gcc/analyzer/ChangeLog: PR analyzer/105899 * kf.cc (kf_strdup::impl_call_pre): Set size of dynamically-allocated buffer. Simulate copying the string from the source region to the new buffer. gcc/testsuite/ChangeLog: PR analyzer/105899 * c-c++-common/analyzer/pr99193-2.c: Add -Wno-analyzer-too-complex. * gcc.dg/analyzer/strdup-1.c: Include "analyzer-decls.h". (test_concrete_strlen): New. (test_symbolic_strlen): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-27analyzer: Move gcc.dg/analyzer tests to c-c++-common (1) [PR96395]benjamin priour1-44/+166
First batch of moving tests from under gcc.dg/analyzer into c-c++-common/analyzer. C builtins are not recognized as such by C++, therefore this patch no longer uses tree.h:fndecl_built_in_p to recognize a builtin function, but rather the function names. Thus functions named as C builtins - such as calloc, sprintf ... - are recognized as such both in C and C++ sources by the analyzer. For user-declared functions named after builtins, the latters' function_decl tree are now preferred over the function_decl the user declared, even when the FE consider their declaration to mismatch (Wbuiltin-declaration-mismatch emitted). This mainly comes into account in the handling of these function attributes : the analyzer uses the builtin's attributes defined in gcc/builtins.def. Signed-off-by: benjamin priour <priour.be@gmail.com> gcc/analyzer/ChangeLog: PR analyzer/96395 * analyzer.h (class known_function): Add virtual casts to builtin_known_function. (class builtin_known_function): New subclass of known_function for builtins. * kf.cc (class kf_alloca): Now derived from builtin_known_function. (class kf_calloc): Likewise. (class kf_free): Likewise. (class kf_malloc): Likewise. (class kf_memcpy_memmove): Likewise. (class kf_memset): Likewise. (class kf_realloc): Likewise. (class kf_strchr): Likewise. (class kf_sprintf): Likewise. (class kf_strcat): Likewise. (class kf_strcpy): Likewise. (class kf_strdup): Likewise. (class kf_strlen): Likewise. (class kf_strndup): Likewise. (register_known_functions): Builtins are now registered as known_functions by name rather than by their BUILTIN_CODE. * known-function-manager.cc (get_normal_builtin): New overload. * known-function-manager.h: New overload declaration. * region-model.cc (region_model::get_builtin_kf): New function. * region-model.h (class region_model): Add declaration of get_builtin_kf. * sm-fd.cc: For called recognized as builtins, use the attributes of that builtin as defined in gcc/builtins.def rather than the user's. * sm-malloc.cc (malloc_state_machine::on_stmt): Likewise. gcc/testsuite/ChangeLog: PR analyzer/96395 * gcc.dg/analyzer/aliasing-3.c: Moved to... * c-c++-common/analyzer/aliasing-3.c: ...here. * gcc.dg/analyzer/aliasing-pr106473.c: Moved to... * c-c++-common/analyzer/aliasing-pr106473.c: ...here. * gcc.dg/analyzer/asm-x86-dyndbg-2.c: Moved to... * c-c++-common/analyzer/asm-x86-dyndbg-2.c: ...here. * gcc.dg/analyzer/asm-x86-lp64-2.c: Moved to... * c-c++-common/analyzer/asm-x86-lp64-2.c: ...here. * gcc.dg/analyzer/atomic-builtins-haproxy-proxy.c: Moved to... * c-c++-common/analyzer/atomic-builtins-haproxy-proxy.c: ...here. * gcc.dg/analyzer/atomic-builtins-qemu-sockets.c: Moved to... * c-c++-common/analyzer/atomic-builtins-qemu-sockets.c: ...here. * gcc.dg/analyzer/attr-malloc-6.c: Moved to... * c-c++-common/analyzer/attr-malloc-6.c: ...here. * gcc.dg/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c: Moved to... * c-c++-common/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c: ...here. * gcc.dg/analyzer/attr-tainted_args-1.c: Moved to... * c-c++-common/analyzer/attr-tainted_args-1.c: ...here. * gcc.dg/analyzer/call-summaries-pr107158.c: Moved to... * c-c++-common/analyzer/call-summaries-pr107158.c: ...here. * gcc.dg/analyzer/calloc-1.c: Moved to... * c-c++-common/analyzer/calloc-1.c: ...here. * gcc.dg/analyzer/compound-assignment-5.c: Moved to... * c-c++-common/analyzer/compound-assignment-5.c: ...here. * gcc.dg/analyzer/coreutils-cksum-pr108664.c: Moved to... * c-c++-common/analyzer/coreutils-cksum-pr108664.c: ...here. * gcc.dg/analyzer/coreutils-sum-pr108666.c: Moved to... * c-c++-common/analyzer/coreutils-sum-pr108666.c: ...here. * gcc.dg/analyzer/deref-before-check-pr108455-1.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr108455-1.c: ...here. * gcc.dg/analyzer/deref-before-check-pr108455-git-pack-revindex.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr108455-git-pack-revindex.c: ...here. * gcc.dg/analyzer/deref-before-check-pr108475-1.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr108475-1.c: ...here. * gcc.dg/analyzer/deref-before-check-pr108475-haproxy-tcpcheck.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr108475-haproxy-tcpcheck.c: ...here. * gcc.dg/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c: ...here. * gcc.dg/analyzer/deref-before-check-pr109239-linux-bus.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr109239-linux-bus.c: ...here. * gcc.dg/analyzer/deref-before-check-pr77425.c: Moved to... * c-c++-common/analyzer/deref-before-check-pr77425.c: ...here. * gcc.dg/analyzer/exec-1.c: Moved to... * c-c++-common/analyzer/exec-1.c: ...here. * gcc.dg/analyzer/feasibility-3.c: Moved to... * c-c++-common/analyzer/feasibility-3.c: ...here. * gcc.dg/analyzer/fields.c: Moved to... * c-c++-common/analyzer/fields.c: ...here. * gcc.dg/analyzer/function-ptr-5.c: Moved to... * c-c++-common/analyzer/function-ptr-5.c: ...here. * gcc.dg/analyzer/infinite-recursion-pr108524-1.c: Moved to... * c-c++-common/analyzer/infinite-recursion-pr108524-1.c: ...here. * gcc.dg/analyzer/infinite-recursion-pr108524-2.c: Moved to... * c-c++-common/analyzer/infinite-recursion-pr108524-2.c: ...here. * gcc.dg/analyzer/infinite-recursion-pr108524-qobject-json-parser.c: Moved to... * c-c++-common/analyzer/infinite-recursion-pr108524-qobject-json-parser.c: ...here. * gcc.dg/analyzer/init.c: Moved to... * c-c++-common/analyzer/init.c: ...here. * gcc.dg/analyzer/inlining-3-multiline.c: Moved to... * c-c++-common/analyzer/inlining-3-multiline.c: ...here. * gcc.dg/analyzer/inlining-3.c: Moved to... * c-c++-common/analyzer/inlining-3.c: ...here. * gcc.dg/analyzer/inlining-4-multiline.c: Moved to... * c-c++-common/analyzer/inlining-4-multiline.c: ...here. * gcc.dg/analyzer/inlining-4.c: Moved to... * c-c++-common/analyzer/inlining-4.c: ...here. * gcc.dg/analyzer/leak-pr105906.c: Moved to... * c-c++-common/analyzer/leak-pr105906.c: ...here. * gcc.dg/analyzer/leak-pr108045-with-call-summaries.c: Moved to... * c-c++-common/analyzer/leak-pr108045-with-call-summaries.c: ...here. * gcc.dg/analyzer/leak-pr108045-without-call-summaries.c: Moved to... * c-c++-common/analyzer/leak-pr108045-without-call-summaries.c: ...here. * gcc.dg/analyzer/leak-pr109059-1.c: Moved to... * c-c++-common/analyzer/leak-pr109059-1.c: ...here. * gcc.dg/analyzer/leak-pr109059-2.c: Moved to... * c-c++-common/analyzer/leak-pr109059-2.c: ...here. * gcc.dg/analyzer/malloc-2.c: Moved to... * c-c++-common/analyzer/malloc-2.c: ...here. * gcc.dg/analyzer/memcpy-2.c: Moved to... * c-c++-common/analyzer/memcpy-2.c: ...here. * gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c: Moved to... * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c: ...here. * gcc.dg/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c: Moved to... * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c: ...here. * gcc.dg/analyzer/null-deref-pr108806-qemu.c: Moved to... * c-c++-common/analyzer/null-deref-pr108806-qemu.c: ...here. * gcc.dg/analyzer/null-deref-pr108830.c: Moved to... * c-c++-common/analyzer/null-deref-pr108830.c: ...here. * gcc.dg/analyzer/pr101962.c: Moved to... * c-c++-common/analyzer/pr101962.c: ...here. * gcc.dg/analyzer/pr103217-2.c: Moved to... * c-c++-common/analyzer/pr103217-2.c: ...here. * gcc.dg/analyzer/pr103217.c: Moved to... * c-c++-common/analyzer/pr103217.c: ...here. * gcc.dg/analyzer/pr104029.c: Moved to... * c-c++-common/analyzer/pr104029.c: ...here. * gcc.dg/analyzer/pr104062.c: Moved to... * c-c++-common/analyzer/pr104062.c: ...here. * gcc.dg/analyzer/pr105783.c: Moved to... * c-c++-common/analyzer/pr105783.c: ...here. * gcc.dg/analyzer/pr107345.c: Moved to... * c-c++-common/analyzer/pr107345.c: ...here. * gcc.dg/analyzer/pr93695-1.c: Moved to... * c-c++-common/analyzer/pr93695-1.c: ...here. * gcc.dg/analyzer/pr94596.c: Moved to... * c-c++-common/analyzer/pr94596.c: ...here. * gcc.dg/analyzer/pr94839.c: Moved to... * c-c++-common/analyzer/pr94839.c: ...here. * gcc.dg/analyzer/pr95152-4.c: C only. * gcc.dg/analyzer/pr95152-5.c: C only. * gcc.dg/analyzer/pr95240.c: Moved to... * c-c++-common/analyzer/pr95240.c: ...here. * gcc.dg/analyzer/pr96639.c: Moved to... * c-c++-common/analyzer/pr96639.c: ...here. * gcc.dg/analyzer/pr96653.c: Moved to... * c-c++-common/analyzer/pr96653.c: ...here. * gcc.dg/analyzer/pr96792.c: Moved to... * c-c++-common/analyzer/pr96792.c: ...here. * gcc.dg/analyzer/pr96841.c: Moved to... * c-c++-common/analyzer/pr96841.c: ...here. * gcc.dg/analyzer/pr98564.c: Moved to... * c-c++-common/analyzer/pr98564.c: ...here. * gcc.dg/analyzer/pr98628.c: Moved to... * c-c++-common/analyzer/pr98628.c: ...here. * gcc.dg/analyzer/pr98969.c: Moved to... * c-c++-common/analyzer/pr98969.c: ...here. * gcc.dg/analyzer/pr99193-2.c: Moved to... * c-c++-common/analyzer/pr99193-2.c: ...here. * gcc.dg/analyzer/pr99193-3.c: Moved to... * c-c++-common/analyzer/pr99193-3.c: ...here. * gcc.dg/analyzer/pr99716-1.c: Moved to... * c-c++-common/analyzer/pr99716-1.c: ...here. * gcc.dg/analyzer/pr99774-1.c: Moved to... * c-c++-common/analyzer/pr99774-1.c: ...here. * gcc.dg/analyzer/realloc-1.c: Moved to... * c-c++-common/analyzer/realloc-1.c: ...here. * gcc.dg/analyzer/realloc-2.c: Moved to... * c-c++-common/analyzer/realloc-2.c: ...here. * gcc.dg/analyzer/realloc-3.c: Moved to... * c-c++-common/analyzer/realloc-3.c: ...here. * gcc.dg/analyzer/realloc-4.c: Moved to... * c-c++-common/analyzer/realloc-4.c: ...here. * gcc.dg/analyzer/realloc-5.c: Moved to... * c-c++-common/analyzer/realloc-5.c: ...here. * gcc.dg/analyzer/realloc-pr110014.c: Moved to... * c-c++-common/analyzer/realloc-pr110014.c: ...here. * gcc.dg/analyzer/snprintf-concat.c: Moved to... * c-c++-common/analyzer/snprintf-concat.c: ...here. * gcc.dg/analyzer/sock-1.c: Moved to... * c-c++-common/analyzer/sock-1.c: ...here. * gcc.dg/analyzer/sprintf-concat.c: Moved to... * c-c++-common/analyzer/sprintf-concat.c: ...here. * gcc.dg/analyzer/string-ops-concat-pair.c: Moved to... * c-c++-common/analyzer/string-ops-concat-pair.c: ...here. * gcc.dg/analyzer/string-ops-dup.c: Moved to... * c-c++-common/analyzer/string-ops-dup.c: ...here. * gcc.dg/analyzer/switch-enum-pr105273-git-vreportf-2.c: Moved to... * c-c++-common/analyzer/switch-enum-pr105273-git-vreportf-2.c: ...here. * gcc.dg/analyzer/symbolic-12.c: Moved to... * c-c++-common/analyzer/symbolic-12.c: ...here. * gcc.dg/analyzer/uninit-alloca.c: Moved to... * c-c++-common/analyzer/uninit-alloca.c: ...here. * gcc.dg/analyzer/untracked-2.c: Moved to... * c-c++-common/analyzer/untracked-2.c: ...here. * gcc.dg/analyzer/vasprintf-1.c: Moved to... * c-c++-common/analyzer/vasprintf-1.c: ...here. * gcc.dg/analyzer/write-to-const-1.c: Moved to... * c-c++-common/analyzer/write-to-const-1.c: ...here. * gcc.dg/analyzer/write-to-function-1.c: C only. * gcc.dg/analyzer/write-to-string-literal-1.c: Moved to... * c-c++-common/analyzer/write-to-string-literal-1.c: ...here. * gcc.dg/analyzer/write-to-string-literal-4-disabled.c: Moved to... * c-c++-common/analyzer/write-to-string-literal-4-disabled.c: ...here. * gcc.dg/analyzer/write-to-string-literal-5.c: Moved to... * c-c++-common/analyzer/write-to-string-literal-5.c: ...here. * g++.dg/analyzer/analyzer.exp: Now also run tests under c-c++-common/analyzer. * gcc.dg/analyzer/analyzer-decls.h: Add NULL definition. * gcc.dg/analyzer/analyzer.exp: Now also run tests under c-c++-common/analyzer. * gcc.dg/analyzer/pr104369-1.c: C only. * gcc.dg/analyzer/pr104369-2.c: Likewise. * gcc.dg/analyzer/pr93355-localealias-feasibility-2.c: Likewise. * gcc.dg/analyzer/sprintf-1.c: Split into C-only and C++-friendly bits. * gcc.dg/analyzer/allocation-size-multiline-1.c: Removed. * gcc.dg/analyzer/allocation-size-multiline-2.c: Removed. * gcc.dg/analyzer/allocation-size-multiline-3.c: Removed. * gcc.dg/analyzer/data-model-11.c: Removed. * gcc.dg/analyzer/pr61861.c: C only. * gcc.dg/analyzer/pr93457.c: Removed. * gcc.dg/analyzer/pr97568.c: Removed. * gcc.dg/analyzer/write-to-string-literal-4.c: Removed. * c-c++-common/analyzer/allocation-size-multiline-1.c: New test. * c-c++-common/analyzer/allocation-size-multiline-2.c: New test. * c-c++-common/analyzer/allocation-size-multiline-3.c: New test. * c-c++-common/analyzer/data-model-11.c: New test. * c-c++-common/analyzer/pr93457.c: New test. * c-c++-common/analyzer/pr97568.c: New test. * c-c++-common/analyzer/sprintf-2.c: C++-friendly bit of previous gcc.dg/analyzer/sprintf-1.c. * c-c++-common/analyzer/write-to-string-literal-4.c: New test.
2023-08-24analyzer: implement kf_strcat [PR105899]David Malcolm1-10/+62
gcc/analyzer/ChangeLog: PR analyzer/105899 * call-details.cc (call_details::check_for_null_terminated_string_arg): Split into overloads, one taking just an arg_idx, the other a new "include_terminator" param. * call-details.h: Likewise. * kf.cc (class kf_strcat): New. (kf_strcpy::impl_call_pre): Update for change to check_for_null_terminated_string_arg. (register_known_functions): Register kf_strcat. * region-model.cc (region_model::check_for_null_terminated_string_arg): Split into overloads, one taking just an arg_idx, the other a new "include_terminator" param. When returning an svalue, handle "include_terminator" being false by subtracting one. * region-model.h (region_model::check_for_null_terminated_string_arg): Split into overloads, one taking just an arg_idx, the other a new "include_terminator" param. gcc/ChangeLog: PR analyzer/105899 * doc/invoke.texi (Static Analyzer Options): Add "strcat" to the list of functions known to the analyzer. gcc/testsuite/ChangeLog: PR analyzer/105899 * gcc.dg/analyzer/strcat-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-24analyzer: reimplement kf_memcpy_memmoveDavid Malcolm1-10/+4
gcc/analyzer/ChangeLog: * kf.cc (kf_memcpy_memmove::impl_call_pre): Reimplement using region_model::copy_bytes. * region-model.cc (region_model::read_bytes): New. (region_model::copy_bytes): New. * region-model.h (region_model::read_bytes): New decl. (region_model::copy_bytes): New decl. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-24analyzer: reimplement kf_strcpy [PR105899]David Malcolm1-18/+14
This patch reimplements the analyzer's implementation of strcpy using the region_model::scan_for_null_terminator infrastructure, so that e.g. it can complain about out-of-bounds reads/writes, unterminated strings, etc. gcc/analyzer/ChangeLog: PR analyzer/105899 * kf.cc (kf_strcpy::impl_call_pre): Reimplement using check_for_null_terminated_string_arg. * region-model.cc (region_model::get_store_bytes): Shortcut reading all of a string_region. (region_model::scan_for_null_terminator): Use get_store_value for the bytes rather than "unknown" when returning an unknown length. (region_model::write_bytes): New. * region-model.h (region_model::write_bytes): New decl. gcc/testsuite/ChangeLog: PR analyzer/105899 * gcc.dg/analyzer/out-of-bounds-diagram-16.c: New test. * gcc.dg/analyzer/strcpy-1.c: Add test coverage. * gcc.dg/analyzer/strcpy-3.c: Likewise. * gcc.dg/analyzer/strcpy-4.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-22analyzer: reimplement kf_strlen [PR105899]David Malcolm1-30/+26
Reimplement kf_strlen in terms of the new string scanning implementation, sharing strlen's implementation with __analyzer_get_strlen. gcc/analyzer/ChangeLog: PR analyzer/105899 * kf-analyzer.cc (class kf_analyzer_get_strlen): Move to kf.cc. (register_known_analyzer_functions): Use make_kf_strlen. * kf.cc (class kf_strlen::impl_call_pre): Replace with implementation of kf_analyzer_get_strlen from kf-analyzer.cc. Handle "UNKNOWN" return from check_for_null_terminated_string_arg by falling back to a conjured svalue. (make_kf_strlen): New. (register_known_functions): Use make_kf_strlen. * known-function-manager.h (make_kf_strlen): New decl. gcc/testsuite/ChangeLog: PR analyzer/105899 * gcc.dg/analyzer/null-terminated-strings-1.c: Update expected results on symbolic values. * gcc.dg/analyzer/strlen-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-21analyzer: add kf_fopenDavid Malcolm1-0/+28
Add checking to -fanalyzer that both params of calls to "fopen" are valid null-terminated strings. gcc/analyzer/ChangeLog: * kf.cc (class kf_fopen): New. (register_known_functions): Register it. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fopen-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-11analyzer: new warning: -Wanalyzer-unterminated-string [PR105899]David Malcolm1-0/+11
This patch adds new functions to the analyzer for checking that an argument at a callsite is a pointer to a valid null-terminated string, and uses this for the following known functions: - error (param 3, the format string) - error_at_line (param 5, the format string) - putenv - strchr (1st param) - strcpy (2nd param) - strdup Currently the check merely detects pointers to unterminated string constants, and adds a new -Wanalyzer-unterminated-string to complain about that. I'm experimenting with detecting other ways in which a buffer can fail to be null-terminated, and for other problems with such buffers, but this patch at least adds the framework for wiring up the check to specific parameters of known_functions. gcc/analyzer/ChangeLog: PR analyzer/105899 * analyzer.opt (Wanalyzer-unterminated-string): New. * call-details.cc (call_details::check_for_null_terminated_string_arg): New. * call-details.h (call_details::check_for_null_terminated_string_arg): New decl. * kf-analyzer.cc (class kf_analyzer_get_strlen): New. (register_known_analyzer_functions): Register it. * kf.cc (kf_error::impl_call_pre): Check that format arg is a valid null-terminated string. (kf_putenv::impl_call_pre): Likewise for the sole param. (kf_strchr::impl_call_pre): Likewise for the first param. (kf_strcpy::impl_call_pre): Likewise for the second param. (kf_strdup::impl_call_pre): Likewise for the sole param. * region-model.cc (get_strlen): New. (struct call_arg_details): New. (inform_about_expected_null_terminated_string_arg): New. (class unterminated_string_arg): New. (region_model::check_for_null_terminated_string_arg): New. * region-model.h (region_model::check_for_null_terminated_string_arg): New decl. gcc/ChangeLog: PR analyzer/105899 * doc/analyzer.texi (__analyzer_get_strlen): New. * doc/invoke.texi: Add -Wanalyzer-unterminated-string. gcc/testsuite/ChangeLog: PR analyzer/105899 * gcc.dg/analyzer/analyzer-decls.h (__analyzer_get_strlen): New. * gcc.dg/analyzer/error-1.c (test_error_unterminated): New. (test_error_at_line_unterminated): New. * gcc.dg/analyzer/null-terminated-strings-1.c: New test. * gcc.dg/analyzer/putenv-1.c (test_unterminated): New. * gcc.dg/analyzer/strchr-1.c (test_unterminated): New. * gcc.dg/analyzer/strcpy-1.c (test_unterminated): New. * gcc.dg/analyzer/strdup-1.c (test_unterminated): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-08-09analyzer: remove default return value from region_model::on_call_preDavid Malcolm1-2/+16
Previously, the code for simulating calls to external functions in region_model::on_call_pre wrote a default svalue to the LHS of the call statement, which could be further overwritten by known_function subclasses. Unfortunately, this led to messy hacks, such as when the default svalue was an allocation: the LHS would be written to with two different heap-allocated regions, requiring special-case cleanups to avoid the stray state from the first heap allocation leading to state explosions; see r14-3001-g021077b94741c9. The following patch eliminates this write of a default svalue to the LHS of callsite. Instead, all known_function implementations that have a return value are now responsible for set the LHS themselves. A new call_details::set_any_lhs_with_defaults function is provided to make it easy to get the old behavior. On working through the various known_function subclasses, I noticed that memset was using the default behavior. That patch updates this so that it's now known to return its first parameter. Cleaning this up eliminates various doubling of saved_diagnostics (e.g. for dubious_allocation_size) where it was generating a diagnostic for both writes to the LHS, deduplicating them to the first diagnostic (with the default LHS), and then failing to create a region_creation_event when emitting the diagnostic, leading to the fallback wording in dubious_allocation_size::describe_final_event, such as: (1) allocated 42 bytes and assigned to ‘int32_t *’ {aka ‘int *’} here; ‘sizeof (int32_t {aka int})’ is ‘4’ Without the double write to the LHS, it creates a region_creation_event, so we get the allocation and the assignment as two separate events in the diagnostic path, e.g.: (1) allocated 42 bytes here (2) assigned to ‘int32_t *’ {aka ‘int *’} here; ‘sizeof (int32_t {aka int})’ is ‘4’ gcc/analyzer/ChangeLog: * analyzer.h (class pure_known_function_with_default_return): New subclass. * call-details.cc (const_fn_p): Move here from region-model.cc. (maybe_get_const_fn_result): Likewise. (get_result_size_in_bytes): Likewise. (call_details::set_any_lhs_with_defaults): New function, based on code in region_model::on_call_pre. * call-details.h (call_details::set_any_lhs_with_defaults): New decl. * diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic): Log the index of the saved_diagnostic. * kf.cc (pure_known_function_with_default_return::impl_call_pre): New. (kf_memset::impl_call_pre): Set the LHS to the first param. (kf_putenv::impl_call_pre): Call cd.set_any_lhs_with_defaults. (kf_sprintf::impl_call_pre): Call cd.set_any_lhs_with_defaults. (class kf_stack_restore): Derive from pure_known_function_with_default_return. (class kf_stack_save): Likewise. (kf_strlen::impl_call_pre): Call cd.set_any_lhs_with_defaults. * region-model-reachability.cc (reachable_regions::handle_sval): Remove logic for symbolic regions for pointers. * region-model.cc (region_model::canonicalize): Remove purging of dynamic extents workaround for surplus values from region_model::on_call_pre's default LHS code. (const_fn_p): Move to call-details.cc. (maybe_get_const_fn_result): Likewise. (get_result_size_in_bytes): Likewise. (region_model::update_for_nonzero_return): Call cd.set_any_lhs_with_defaults. (region_model::on_call_pre): Remove the assignment to the LHS of a default return value, instead requiring all known_function implementations to write to any LHS of the call. Use cd.set_any_lhs_with_defaults on the non-kf paths. * sm-fd.cc (kf_socket::outcome_of_socket::update_model): Use cd.set_any_lhs_with_defaults when failing to get at fd state. (kf_bind::outcome_of_bind::update_model): Likewise. (kf_listen::outcome_of_listen::update_model): Likewise. (kf_accept::outcome_of_accept::update_model): Likewise. (kf_connect::outcome_of_connect::update_model): Likewise. (kf_read::impl_call_pre): Use cd.set_any_lhs_with_defaults. * sm-file.cc (class kf_stdio_output_fn): Derive from pure_known_function_with_default_return. (class kf_ferror): Likewise. (class kf_fileno): Likewise. (kf_fgets::impl_call_pre): Use cd.set_any_lhs_with_defaults. (kf_read::impl_call_pre): Likewise. (class kf_getc): Derive from pure_known_function_with_default_return. (class kf_getchar): Likewise. * varargs.cc (kf_va_arg::impl_call_pre): Use cd.set_any_lhs_with_defaults. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/allocation-size-1.c: Update expected results to reflect splitting of allocation size and assignment messages from a single event into pairs of events * gcc.dg/analyzer/allocation-size-2.c: Likewise. * gcc.dg/analyzer/allocation-size-3.c: Likewise. * gcc.dg/analyzer/allocation-size-4.c: Likewise. * gcc.dg/analyzer/allocation-size-multiline-1.c: Likewise. * gcc.dg/analyzer/allocation-size-multiline-2.c: Likewise. * gcc.dg/analyzer/allocation-size-multiline-3.c: Likewise. * gcc.dg/analyzer/memset-1.c (test_1): Verify that the return value is the initial argument. * gcc.dg/plugin/analyzer_kernel_plugin.c (copy_across_boundary_fn::impl_call_pre): Ensure the LHS is set on the "known zero size" case. * gcc.dg/plugin/analyzer_known_fns_plugin.c (known_function_attempt_to_copy::impl_call_pre): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-06-21analyzer: add text-art visualizations of out-of-bounds accesses [PR106626]David Malcolm1-2/+4
This patch extends -Wanalyzer-out-of-bounds so that, where possible, it will emit a text art diagram visualizing the spatial relationship between (a) the memory region that the analyzer predicts would be accessed, versus (b) the range of memory that is valid to access - whether they overlap, are touching, are close or far apart; which one is before or after in memory, the relative sizes involved, the direction of the access (read vs write), and, in some cases, the values of data involved. This diagram can be suppressed using -fdiagnostics-text-art-charset=none. For example, given: int32_t arr[10]; int32_t int_arr_read_element_before_start_far(void) { return arr[-100]; } it emits: demo-1.c: In function ‘int_arr_read_element_before_start_far’: demo-1.c:7:13: warning: buffer under-read [CWE-127] [-Wanalyzer-out-of-bounds] 7 | return arr[-100]; | ~~~^~~~~~ ‘int_arr_read_element_before_start_far’: event 1 | | 7 | return arr[-100]; | | ~~~^~~~~~ | | | | | (1) out-of-bounds read from byte -400 till byte -397 but ‘arr’ starts at byte 0 | demo-1.c:7:13: note: valid subscripts for ‘arr’ are ‘[0]’ to ‘[9]’ ┌───────────────────────────┐ │read of ‘int32_t’ (4 bytes)│ └───────────────────────────┘ ^ │ │ ┌───────────────────────────┐ ┌────────┬────────┬─────────┐ │ │ │ [0] │ ... │ [9] │ │ before valid range │ ├────────┴────────┴─────────┤ │ │ │‘arr’ (type: ‘int32_t[10]’)│ └───────────────────────────┘ └───────────────────────────┘ ├─────────────┬─────────────┤├─────┬──────┤├─────────────┬─────────────┤ │ │ │ ╭────────────┴───────────╮ ╭────┴────╮ ╭───────┴──────╮ │⚠️ under-read of 4 bytes│ │396 bytes│ │size: 40 bytes│ ╰────────────────────────╯ ╰─────────╯ ╰──────────────╯ and given: #include <string.h> void test_non_ascii () { char buf[5]; strcpy (buf, "文字化け"); } it emits: demo-2.c: In function ‘test_non_ascii’: demo-2.c:7:3: warning: stack-based buffer overflow [CWE-121] [-Wanalyzer-out-of-bounds] 7 | strcpy (buf, "文字化け"); | ^~~~~~~~~~~~~~~~~~~~~~~~ ‘test_non_ascii’: events 1-2 | | 6 | char buf[5]; | | ^~~ | | | | | (1) capacity: 5 bytes | 7 | strcpy (buf, "文字化け"); | | ~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) out-of-bounds write from byte 5 till byte 12 but ‘buf’ ends at byte 5 | demo-2.c:7:3: note: write of 8 bytes to beyond the end of ‘buf’ 7 | strcpy (buf, "文字化け"); | ^~~~~~~~~~~~~~~~~~~~~~~~ demo-2.c:7:3: note: valid subscripts for ‘buf’ are ‘[0]’ to ‘[4]’ ┌─────┬─────┬─────┬────┬────┐┌────┬────┬────┬────┬────┬────┬────┬──────┐ │ [0] │ [1] │ [2] │[3] │[4] ││[5] │[6] │[7] │[8] │[9] │[10]│[11]│ [12] │ ├─────┼─────┼─────┼────┼────┤├────┼────┼────┼────┼────┼────┼────┼──────┤ │0xe6 │0x96 │0x87 │0xe5│0xad││0x97│0xe5│0x8c│0x96│0xe3│0x81│0x91│ 0x00 │ ├─────┴─────┴─────┼────┴────┴┴────┼────┴────┴────┼────┴────┴────┼──────┤ │ U+6587 │ U+5b57 │ U+5316 │ U+3051 │U+0000│ ├─────────────────┼───────────────┼──────────────┼──────────────┼──────┤ │ 文 │ 字 │ 化 │ け │ NUL │ ├─────────────────┴───────────────┴──────────────┴──────────────┴──────┤ │ string literal (type: ‘char[13]’) │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ v v v v v v v v v v v v v ┌─────┬────────────────┬────┐┌─────────────────────────────────────────┐ │ [0] │ ... │[4] ││ │ ├─────┴────────────────┴────┤│ after valid range │ │ ‘buf’ (type: ‘char[5]’) ││ │ └───────────────────────────┘└─────────────────────────────────────────┘ ├─────────────┬─────────────┤├────────────────────┬────────────────────┤ │ │ ╭────────┴────────╮ ╭───────────┴──────────╮ │capacity: 5 bytes│ │⚠️ overflow of 8 bytes│ ╰─────────────────╯ ╰──────────────────────╯ showing that the overflow occurs partway through the UTF-8 encoding of the U+5b57 code point. There are lots more examples in the test suite. It doesn't show up in this email, but the above diagrams are colorized to constrast the valid and invalid access ranges. gcc/ChangeLog: PR analyzer/106626 * Makefile.in (ANALYZER_OBJS): Add analyzer/access-diagram.o. * doc/invoke.texi (Wanalyzer-out-of-bounds): Add description of text art. (fanalyzer-debug-text-art): New. gcc/analyzer/ChangeLog: PR analyzer/106626 * access-diagram.cc: New file. * access-diagram.h: New file. * analyzer.h (class region_offset): Add default ctor. (region_offset::make_byte_offset): New decl. (region_offset::concrete_p): New. (region_offset::get_concrete_byte_offset): New. (region_offset::calc_symbolic_bit_offset): New decl. (region_offset::calc_symbolic_byte_offset): New decl. (region_offset::dump_to_pp): New decl. (region_offset::dump): New decl. (operator<, operator<=, operator>, operator>=): New decls for region_offset. * analyzer.opt (-param=analyzer-text-art-string-ellipsis-threshold=): New. (-param=analyzer-text-art-string-ellipsis-head-len=): New. (-param=analyzer-text-art-string-ellipsis-tail-len=): New. (-param=analyzer-text-art-ideal-canvas-width=): New. (fanalyzer-debug-text-art): New. * bounds-checking.cc: Include "intl.h", "diagnostic-diagram.h", and "analyzer/access-diagram.h". (class out_of_bounds::oob_region_creation_event_capacity): New. (out_of_bounds::out_of_bounds): Add "model" and "sval_hint" params. (out_of_bounds::mark_interesting_stuff): Use the base region. (out_of_bounds::add_region_creation_events): Use oob_region_creation_event_capacity. (out_of_bounds::get_dir): New pure vfunc. (out_of_bounds::maybe_show_notes): New. (out_of_bounds::maybe_show_diagram): New. (out_of_bounds::make_access_diagram): New. (out_of_bounds::m_model): New field. (out_of_bounds::m_sval_hint): New field. (out_of_bounds::m_region_creation_event_id): New field. (concrete_out_of_bounds::concrete_out_of_bounds): Update for new fields. (concrete_past_the_end::concrete_past_the_end): Likewise. (concrete_past_the_end::add_region_creation_events): Use oob_region_creation_event_capacity. (concrete_buffer_overflow::concrete_buffer_overflow): Update for new fields. (concrete_buffer_overflow::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_overflow::get_dir): New. (concrete_buffer_over_read::concrete_buffer_over_read): Update for new fields. (concrete_buffer_over_read::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_overflow::get_dir): New. (concrete_buffer_underwrite::concrete_buffer_underwrite): Update for new fields. (concrete_buffer_underwrite::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_underwrite::get_dir): New. (concrete_buffer_under_read::concrete_buffer_under_read): Update for new fields. (concrete_buffer_under_read::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_under_read::get_dir): New. (symbolic_past_the_end::symbolic_past_the_end): Update for new fields. (symbolic_buffer_overflow::symbolic_buffer_overflow): Likewise. (symbolic_buffer_overflow::emit): Call maybe_show_notes. (symbolic_buffer_overflow::get_dir): New. (symbolic_buffer_over_read::symbolic_buffer_over_read): Update for new fields. (symbolic_buffer_over_read::emit): Call maybe_show_notes. (symbolic_buffer_over_read::get_dir): New. (region_model::check_symbolic_bounds): Add "sval_hint" param. Pass it and sized_offset_reg to diagnostics. (region_model::check_region_bounds): Add "sval_hint" param, passing it to diagnostics. * diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic): Pass logger to pending_diagnostic::emit. * engine.cc: Add logger param to pending_diagnostic::emit implementations. * infinite-recursion.cc: Likewise. * kf-analyzer.cc: Likewise. * kf.cc: Likewise. Add nullptr for new param of check_region_for_write. * pending-diagnostic.h: Likewise in decl. * region-model-manager.cc (region_model_manager::get_or_create_int_cst): Convert param from poly_int64 to const poly_wide_int_ref &. (region_model_manager::maybe_fold_binop): Support type being NULL when checking for floating-point types. Check for (X + Y) - X => Y. Be less strict about types when folding associative ops. Check for (X + Y) * CST => (X * CST) + (Y * CST). * region-model-manager.h (region_model_manager::get_or_create_int_cst): Convert param from poly_int64 to const poly_wide_int_ref &. * region-model.cc: Add logger param to pending_diagnostic::emit implementations. (region_model::check_external_function_for_access_attr): Update for new param of check_region_for_write. (region_model::deref_rvalue): Use nullptr rather than NULL. (region_model::get_capacity): Handle RK_STRING. (region_model::check_region_access): Add "sval_hint" param; pass it to check_region_bounds. (region_model::check_region_for_write): Add "sval_hint" param; pass it to check_region_access. (region_model::check_region_for_read): Add NULL for new param to check_region_access. (region_model::set_value): Pass rhs_sval to check_region_for_write. (region_model::get_representative_path_var_1): Handle SK_CONSTANT in the check for infinite recursion. * region-model.h (region_model::check_region_for_write): Add "sval_hint" param. (region_model::check_region_access): Likewise. (region_model::check_symbolic_bounds): Likewise. (region_model::check_region_bounds): Likewise. * region.cc (region_offset::make_byte_offset): New. (region_offset::calc_symbolic_bit_offset): New. (region_offset::calc_symbolic_byte_offset): New. (region_offset::dump_to_pp): New. (region_offset::dump): New. (struct linear_op): New. (operator<, operator<=, operator>, operator>=): New, for region_offset. (region::get_next_offset): New. (region::get_relative_symbolic_offset): Use ptrdiff_type_node. (field_region::get_relative_symbolic_offset): Likewise. (element_region::get_relative_symbolic_offset): Likewise. (bit_range_region::get_relative_symbolic_offset): Likewise. * region.h (region::get_next_offset): New decl. * sm-fd.cc: Add logger param to pending_diagnostic::emit implementations. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-pattern-test.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * store.cc (bit_range::contains_p): Allow "out" to be null. * store.h (byte_range::get_start_bit_offset): New. (byte_range::get_next_bit_offset): New. * varargs.cc: Add logger param to pending_diagnostic::emit implementations. gcc/testsuite/ChangeLog: PR analyzer/106626 * gcc.dg/analyzer/data-model-1.c (test_16): Update for out-of-bounds working. * gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-json.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-10.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-11.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-12.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-13.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-14.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-15.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-2.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-3.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-4.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-6.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-7.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-8.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-9.c: New test. * gcc.dg/analyzer/pattern-test-2.c: Update expected results. * gcc.dg/analyzer/pr101962.c: Update expected results. * gcc.dg/plugin/analyzer_gil_plugin.c: Add logger param to pending_diagnostic::emit implementations. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-06-02analyzer: implement various atomic builtins [PR109015]David Malcolm1-0/+355
This patch implements many of the __atomic_* builtins from sync-builtins.def as known_function subclasses within the analyzer. gcc/analyzer/ChangeLog: PR analyzer/109015 * kf.cc (class kf_atomic_exchange): New. (class kf_atomic_exchange_n): New. (class kf_atomic_fetch_op): New. (class kf_atomic_op_fetch): New. (class kf_atomic_load): New. (class kf_atomic_load_n): New. (class kf_atomic_store_n): New. (register_atomic_builtins): New function. (register_known_functions): Call register_atomic_builtins. gcc/testsuite/ChangeLog: PR analyzer/109015 * gcc.dg/analyzer/atomic-builtins-1.c: New test. * gcc.dg/analyzer/atomic-builtins-haproxy-proxy.c: New test. * gcc.dg/analyzer/atomic-builtins-qemu-sockets.c: New test. * gcc.dg/analyzer/atomic-types-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-03-03analyzer: provide placeholder implementation of sprintfDavid Malcolm1-0/+29
Previously, the analyzer lacked a known_function implementation of sprintf, and thus would handle calls to sprintf with the "anything could happen" fallback. Whilst working on PR analyzer/107565 I noticed that this was preventing a lot of genuine memory leaks from being reported for Doom; fixing thusly. Integration testing of the effect of the patch shows a big increase in true positives due to the case mentioned in Doom, and one new false positive (in pcre2), which I'm tracking as PR analyzer/109014. Comparison: GOOD: 67 -> 123 (+56); 10.91% -> 18.33% BAD: 547 -> 548 (+1) where the affected warnings/projects are: -Wanalyzer-malloc-leak: GOOD: 0 -> 56 (+56); 0.00% -> 41.48% BAD: 79 True positives: 0 -> 56 (+56) (all in Doom) -Wanalyzer-use-of-uninitialized-value: GOOD: 0; 0.00% BAD: 80 -> 81 (+1) False positives: pcre2-10.42: 0 -> 1 (+1) gcc/analyzer/ChangeLog: * kf.cc (class kf_sprintf): New. (register_known_functions): Register it. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/doom-d_main-IdentifyVersion.c: New test. * gcc.dg/analyzer/sprintf-1.c: New test. * gcc.dg/analyzer/sprintf-concat.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-03-02analyzer: Support errno for newlibHans-Peter Nilsson1-0/+2
Without this definition, the errno definition for newlib isn't recognized as such, and these tests fail for newlib targets: FAIL: gcc.dg/analyzer/call-summaries-errno.c (test for warnings, line 16) FAIL: gcc.dg/analyzer/call-summaries-errno.c (test for excess errors) FAIL: gcc.dg/analyzer/errno-1.c (test for warnings, line 20) FAIL: gcc.dg/analyzer/errno-1.c (test for excess errors) FAIL: gcc.dg/analyzer/flex-without-call-summaries.c (test for excess errors) FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 31) FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 35) FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 46) FAIL: gcc.dg/analyzer/isatty-1.c (test for warnings, line 56) FAIL: gcc.dg/analyzer/isatty-1.c (test for excess errors) gcc/analyzer: * kf.cc (register_known_functions): Add __errno function for newlib.
2023-01-16Update copyright years.Jakub Jelinek1-1/+1
2023-01-11analyzer: fix leak false positives on "*UNKNOWN = PTR;" [PR108252]David Malcolm1-0/+56
PR analyzer/108252 reports a false positive from -Wanalyzer-malloc-leak on code like this: *ptr_ptr = strdup(EXPR); where ptr_ptr is an UNKNOWN_VALUE. When we handle: *UNKNOWN = PTR; store::set_value normally marks *PTR as having escaped, and this means we don't report PTR as leaking when the last usage of PTR is lost. However this only works for cases where PTR is a region_svalue. In the example in the bug, it's a conjured_svalue, rather than a region_svalue. A similar problem can arise for FDs, which aren't pointers. This patch fixes the bug by updating store::set_value to mark any values stored via *UNKNOWN = VAL as not leaking. Additionally, sm-malloc.cc's known_allocator_p hardcodes strdup and strndup as allocators (and thus transitioning their result to "unchecked"), but we don't implement known_functions for these, leading to the LHS being a CONJURED_SVALUE, rather than a region_svalue to a heap-allocated region. A similar issue happens with functions marked with __attribute__((malloc)). As part of a "belt and braces" fix, the patch also updates the handling of these functions, so that they use heap-allocated regions. gcc/analyzer/ChangeLog: PR analyzer/108252 * kf.cc (class kf_strdup): New. (class kf_strndup): New. (register_known_functions): Register them. * region-model.cc (region_model::on_call_pre): Use &HEAP_ALLOCATED_REGION for the default result of an external function with the "malloc" attribute, rather than CONJURED_SVALUE. (region_model::get_or_create_region_for_heap_alloc): Allow "size_in_bytes" to be NULL. * store.cc (store::set_value): When handling *UNKNOWN = VAL, mark VAL as "maybe bound". gcc/testsuite/ChangeLog: PR analyzer/108252 * gcc.dg/analyzer/attr-malloc-pr108252.c: New test. * gcc.dg/analyzer/fd-leak-pr108252.c: New test. * gcc.dg/analyzer/flex-with-call-summaries.c: Remove xfail from warning false +ve directives. * gcc.dg/analyzer/pr103217-2.c: Add -Wno-analyzer-too-complex. * gcc.dg/analyzer/pr103217-3.c: Likewise. * gcc.dg/analyzer/strdup-pr108252.c: New test. * gcc.dg/analyzer/strndup-pr108252.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-16analyzer: add src_region param to region_model::check_for_poison [PR106479]David Malcolm1-1/+1
PR analyzer/106479 notes that we don't always show the region-creation event for a memmove from an uninitialized stack region. This occurs when using kf_memcpy_memmove. Fix by passing a src_region hint to region_model::check_for_poison. gcc/analyzer/ChangeLog: PR analyzer/106479 * kf.cc (kf_memcpy_memmove::impl_call_pre): Pass in source region to region_model::check_for_poison. * region-model-asm.cc (region_model::on_asm_stmt): Pass NULL region to region_model::check_for_poison. * region-model.cc (region_model::check_for_poison): Add "src_region" param, and pass it to poisoned_value_diagnostic. (region_model::on_assignment): Pass NULL region to region_model::check_for_poison. (region_model::get_rvalue): Likewise. * region-model.h (region_model::check_for_poison): Add "src_region" param. * sm-fd.cc (fd_state_machine::on_accept): Pass in source region to region_model::check_for_poison. * varargs.cc (kf_va_copy::impl_call_pre): Pass NULL region to region_model::check_for_poison. (kf_va_arg::impl_call_pre): Pass in source region to region_model::check_for_poison. gcc/testsuite/ChangeLog: PR analyzer/106479 * gcc.dg/analyzer/pr104308.c (test_memmove_within_uninit): Remove xfail on region creation event. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-12-08analyzer: rename region-model-impl-calls.cc to kf.ccDavid Malcolm1-0/+991
gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Update for renaming of analyzer/region-model-impl-calls.cc to analyzer/kf.cc. gcc/analyzer/ChangeLog: * analyzer.h (class known_function): Expand comment. * region-model-impl-calls.cc: Rename to... * kf.cc: ...this. * known-function-manager.h (class known_function_manager): Add leading comment. Signed-off-by: David Malcolm <dmalcolm@redhat.com>