Age | Commit message (Collapse) | Author | Files | Lines |
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
[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>
|
|
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>
|
|
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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.
|
|
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>
|
|
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>
|
|
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.
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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.
|
|
|
|
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>
|
|
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>
|
|
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>
|