aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/sm-fd.cc
AgeCommit message (Collapse)AuthorFilesLines
2024-07-04analyzer: convert sm_context * to sm_context &David Malcolm1-159/+159
These are never nullptr and never change, so use a reference rather than a pointer. No functional change intended. gcc/analyzer/ChangeLog: * diagnostic-manager.cc (diagnostic_manager::add_events_for_eedge): Pass sm_ctxt by reference. * engine.cc (impl_region_model_context::on_condition): Likewise. (impl_region_model_context::on_bounded_ranges): Likewise. (impl_region_model_context::on_phi): Likewise. (exploded_node::on_stmt): Likewise. * sm-fd.cc: Update all uses of sm_context * to sm_context &. * 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. * sm.h: Likewise. * varargs.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: Update all uses of sm_context * to sm_context &. 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-01-03Update copyright years.Jakub Jelinek1-1/+1
2023-12-01diagnostics, analyzer: add optional per-diagnostic property bags to SARIFDavid Malcolm1-46/+29
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-08-27analyzer: Move gcc.dg/analyzer tests to c-c++-common (1) [PR96395]benjamin priour1-6/+19
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-09analyzer: remove default return value from region_model::on_call_preDavid Malcolm1-10/+41
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-7/+7
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-02-07analyzer: fix -Wanalyzer-use-of-uninitialized-value false +ve on "read" ↵David Malcolm1-0/+33
[PR108661] My integration testing shows many false positives from -Wanalyzer-use-of-uninitialized-value. One cause turns out to be that as of r13-1404-g97baacba963c06 fd_state_machine::on_stmt recognizes calls to "read", and returns true, so that region_model::on_call_post doesn't call handle_unrecognized_call on them, and so the analyzer erroneously "thinks" that the buffer pointed to by "read" is never touched by the "read" call. This works for "fread" because sm-file.cc implements kf_fread, which handles calls to "fread" by clobbering the buffer pointed to. In the long term we should probably be smarter about this and bifurcate the analysis to consider e.g. errors vs full reads vs partial reads, etc (which I'm tracking in PR analyzer/108689). In the meantime, this patch adds a kf_read for "read" analogous to the one for "fread", fixing 6 false positives seen in git-2.39.0 and 2 in haproxy-2.7.1. gcc/analyzer/ChangeLog: PR analyzer/108661 * sm-fd.cc (class kf_read): New. (register_known_fd_functions): Register "read". * sm-file.cc (class kf_fread): Update comment. gcc/testsuite/ChangeLog: PR analyzer/108661 * gcc.dg/analyzer/fread-pr108661.c: New test. * gcc.dg/analyzer/read-pr108661.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-02-02analyzer: fix -Wanalyzer-fd-type-mismatch false +ve on "listen" [PR108633]David Malcolm1-2/+6
gcc/analyzer/ChangeLog: PR analyzer/108633 * sm-fd.cc (fd_state_machine::check_for_fd_attrs): Add missing "continue". (fd_state_machine::on_listen): Don't issue phase-mismatch or type-mismatch warnings for the "invalid" state. gcc/testsuite/ChangeLog: PR analyzer/108633 * gcc.dg/analyzer/fd-pr108633.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-01-16Update copyright years.Jakub Jelinek1-1/+1
2022-12-16analyzer: add src_region param to region_model::check_for_poison [PR106479]David Malcolm1-0/+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-06analyzer: split out more stuff from region-model-impl-calls.ccDavid Malcolm1-0/+1
gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Add analyzer/call-details.o, analyzer/kf-analyzer.o, and kf-lang-cp.o. gcc/analyzer/ChangeLog: * analyzer.h (register_known_analyzer_functions): New decl. (register_known_functions_lang_cp): New decl. * call-details.cc: New file, split out from region-model-impl-calls.cc. * call-details.h: New file, split out from region-model.h. * call-info.cc: Include "analyzer/call-details.h". * call-summary.h: Likewise. * kf-analyzer.cc: New file, split out from region-model-impl-calls.cc. * kf-lang-cp.cc: Likewise. * known-function-manager.cc: Include "analyzer/call-details.h". * region-model-impl-calls.cc: Move definitions of call_details's member functions to call-details.cc. Move class kf_analyzer_* to kf-analyzer.cc. Move kf_operator_new and kf_operator_delete to kf-lang-cp.cc. Refresh #includes accordingly. (register_known_functions): Replace registration of __analyzer_* functions with a call to register_known_analyzer_functions. Replace registration of C++ support functions with a call to register_known_functions_lang_cp. * region-model.h (class call_details): Move to new call-details.h. * sm-fd.cc: Include "analyzer/call-details.h". * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * varargs.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: Include "analyzer/call-details.h". * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-30analyzer: fix ICE on bind/connect with a constant fd [PR107928]David Malcolm1-2/+4
gcc/analyzer/ChangeLog: PR analyzer/107928 * sm-fd.cc (fd_state_machine::on_bind): Handle m_constant_fd in the "success" outcome. (fd_state_machine::on_connect): Likewise. * sm-fd.dot: Add "constant_fd" state and its transitions. gcc/testsuite/ChangeLog: PR analyzer/107928 * gcc.dg/analyzer/fd-bind-pr107928.c: New test. * gcc.dg/analyzer/fd-connect-pr107928.c: New test. * gcc.dg/analyzer/fd-stream-socket-active-open.c (test_active_open_from_connect_constant): New, adapted from test_active_open_from_connect. * gcc.dg/analyzer/fd-stream-socket-passive-open.c (test_passive_open_from_bind_constant): New, adapted from test_passive_open_from_bind. (test_passive_open_from_listen_constant): New, adapted from test_passive_open_from_listen. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-29analyzer work on issues with flex-generated lexers [PR103546]David Malcolm1-0/+79
PR analyzer/103546 tracks various false positives seen on flex-generated lexers. Whilst investigating them, I noticed an ICE with -fanalyzer-call-summaries due to attempting to store sm-state for an UNKNOWN svalue, which this patch fixes. This patch also provides known_function implementations of all of the external functions called by the lexer, reducing the number of false positives. The patch doesn't eliminate all false positives, but adds integration tests to try to establish a baseline from which the remaining false positives can be fixed. gcc/analyzer/ChangeLog: PR analyzer/103546 * analyzer.h (register_known_file_functions): New decl. * program-state.cc (sm_state_map::replay_call_summary): Rejct attempts to store sm-state for caller_sval that can't have associated state. * region-model-impl-calls.cc (register_known_functions): Call register_known_file_functions. * sm-fd.cc (class kf_isatty): New. (register_known_fd_functions): Register it. * sm-file.cc (class kf_ferror): New. (class kf_fileno): New. (class kf_getc): New. (register_known_file_functions): New. gcc/ChangeLog: PR analyzer/103546 * doc/invoke.texi (Static Analyzer Options): Add isatty, ferror, fileno, and getc to the list of functions known to the analyzer. gcc/testsuite/ChangeLog: PR analyzer/103546 * gcc.dg/analyzer/ferror-1.c: New test. * gcc.dg/analyzer/fileno-1.c: New test. * gcc.dg/analyzer/flex-with-call-summaries.c: New test. * gcc.dg/analyzer/flex-without-call-summaries.c: New test. * gcc.dg/analyzer/getc-1.c: New test. * gcc.dg/analyzer/isatty-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-23analyzer: eliminate region_model::on_ fns for socketsDavid Malcolm1-95/+49
This mostly mechanical patch eliminates a confusing extra layer of redundant calls in the handling of socket-related functions. gcc/analyzer/ChangeLog: * region-model.h (region_model::on_socket): Delete decl. (region_model::on_bind): Likewise. (region_model::on_listen): Likewise. (region_model::on_accept): Likewise. (region_model::on_connect): Likewise. * sm-fd.cc (kf_socket::outcome_of_socket::update_model): Move body of region_model::on_socket into here, ... (region_model::on_socket): ...eliminating this function. (kf_bind::outcome_of_bind::update_model): Likewise for on_bind... (region_model::on_bind): ...eliminating this function. (kf_listen::outcome_of_listen::update_model): Likewise fo on_listen... (region_model::on_listen): ...eliminating this function. (kf_accept::outcome_of_accept::update_model): Likewise fo on_accept... (region_model::on_accept): ...eliminating this function. (kf_connect::outcome_of_connect::update_model): Likewise fo on_connect... (region_model::on_connect): ...eliminating this function. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-23analyzer: move known funs for fds to sm-fd.ccDavid Malcolm1-0/+293
This mostly mechanical change enables a simplification in the followup patch. No functional change intended. gcc/analyzer/ChangeLog: * analyzer.h (register_known_fd_functions): New decl. * region-model-impl-calls.cc (class kf_accept): Move to sm-fd.cc. (class kf_bind): Likewise. (class kf_connect): Likewise. (class kf_listen): Likewise. (class kf_pipe): Likewise. (class kf_socket): Likewise. (register_known_functions): Remove registration of the above functions, instead calling register_known_fd_functions. * sm-fd.cc: Include "analyzer/call-info.h". (class kf_socket): Move here from region-model-impl-calls.cc. (class kf_bind): Likewise. (class kf_listen): Likewise. (class kf_accept): Likewise. (class kf_connect): Likewise. (class kf_pipe): Likewise. (register_known_fd_functions): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-22analyzer: fix ICE on 'bind(INT_CST, ...)' [PR107783]David Malcolm1-3/+6
This was crashing inside fd_phase_mismatch's ctor with assertion failure when the state was "fd-constant". Fix the ICE by not complaining about constants passed to these APIs. gcc/analyzer/ChangeLog: PR analyzer/107783 * sm-fd.cc (fd_state_machine::check_for_new_socket_fd): Don't complain when old state is "fd-constant". (fd_state_machine::on_listen): Likewise. (fd_state_machine::on_accept): Likewise. gcc/testsuite/ChangeLog: PR analyzer/107783 * gcc.dg/analyzer/fd-accept.c (test_accept_on_constant): New. * gcc.dg/analyzer/fd-bind.c (test_bind_on_constant): New. * gcc.dg/analyzer/fd-connect.c (test_connect_on_constant): New. * gcc.dg/analyzer/fd-listen.c (test_listen_on_connected_socket): Fix typo. (test_listen_on_constant): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-18analyzer: move more impl_* to known_functionDavid Malcolm1-6/+6
Fix a missing check that the argument to __analyzer_dump_capacity must be a pointer type (which would otherwise lead to an ICE). Do so by using the known_function_manager rather than by doing lots of string matching. Do the same for many other functions. Doing so moves the type-checking closer to the logic that makes use of it, by putting them in the same class, rather than splitting them up between two source files (and sometimes three, e.g. for "pipe"). I hope this reduces the number of missing checks. gcc/analyzer/ChangeLog: * analyzer.cc (is_pipe_call_p): Delete. * analyzer.h (is_pipe_call_p): Delete. * region-model-impl-calls.cc (call_details::get_location): New. (class kf_analyzer_break): New, adapted from region_model::on_stmt_pre. (region_model::impl_call_analyzer_describe): Convert to... (class kf_analyzer_describe): ...this. (region_model::impl_call_analyzer_dump_capacity): Convert to... (class kf_analyzer_dump_capacity): ...this. (region_model::impl_call_analyzer_dump_escaped): Convert to... (class kf_analyzer_dump_escaped): ...this. (class kf_analyzer_dump_exploded_nodes): New. (region_model::impl_call_analyzer_dump_named_constant): Convert to... (class kf_analyzer_dump_named_constant): ...this. (class dump_path_diagnostic): Move here from region-model.cc. (class kf_analyzer_dump_path) New, adapted from region_model::on_stmt_pre. (class kf_analyzer_dump_region_model): Likewise. (region_model::impl_call_analyzer_eval): Convert to... (class kf_analyzer_eval): ...this. (region_model::impl_call_analyzer_get_unknown_ptr): Convert to... (class kf_analyzer_get_unknown_ptr): ...this. (class known_function_accept): Rename to... (class kf_accept): ...this. (class known_function_bind): Rename to... (class kf_bind): ...this. (class known_function_connect): Rename to... (class kf_connect): ...this. (region_model::impl_call_errno_location): Convert to... (class kf_errno_location): ...this. (class known_function_listen): Rename to... (class kf_listen): ...this. (region_model::impl_call_pipe): Convert to... (class kf_pipe): ...this. (region_model::impl_call_putenv): Convert to... (class kf_putenv): ...this. (region_model::impl_call_operator_new): Convert to... (class kf_operator_new): ...this. (region_model::impl_call_operator_delete): Convert to... (class kf_operator_delete): ...this. (class known_function_socket): Rename to... (class kf_socket): ...this. (register_known_functions): Rename param to KFM. Break out existing known functions into a "POSIX" section, and add "pipe", "pipe2", and "putenv". Add debugging functions "__analyzer_break", "__analyzer_describe", "__analyzer_dump_capacity", "__analyzer_dump_escaped", "__analyzer_dump_exploded_nodes", "__analyzer_dump_named_constant", "__analyzer_dump_path", "__analyzer_dump_region_model", "__analyzer_eval", "__analyzer_get_unknown_ptr". Add C++ support functions "operator new", "operator new []", "operator delete", and "operator delete []". * region-model.cc (class dump_path_diagnostic): Move to region-model-impl-calls.cc. (region_model::on_stmt_pre): Eliminate special-casing of "__analyzer_describe", "__analyzer_dump_capacity", "__analyzer_dump_escaped", "__analyzer_dump_named_constant", "__analyzer_dump_path", "__analyzer_dump_region_model", "__analyzer_eval", "__analyzer_break", "__analyzer_dump_exploded_nodes", "__analyzer_get_unknown_ptr", "__errno_location", "pipe", "pipe2", "putenv", "operator new", "operator new []", "operator delete", "operator delete []" "pipe" and "pipe2", handling them instead via the known_functions mechanism. * region-model.h (call_details::get_location): New decl. (region_model::impl_call_analyzer_describe): Delete decl. (region_model::impl_call_analyzer_dump_capacity): Delete decl. (region_model::impl_call_analyzer_dump_escaped): Delete decl. (region_model::impl_call_analyzer_dump_named_constant): Delete decl. (region_model::impl_call_analyzer_eval): Delete decl. (region_model::impl_call_analyzer_get_unknown_ptr): Delete decl. (region_model::impl_call_errno_location): Delete decl. (region_model::impl_call_pipe): Delete decl. (region_model::impl_call_putenv): Delete decl. (region_model::impl_call_operator_new): Delete decl. (region_model::impl_call_operator_delete): Delete decl. * sm-fd.cc: Update comments. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-debugging-fns-1.c: New test. * gcc.dg/analyzer/attr-const-3.c: Increase the "analyzer-max-svalue-depth" from 0 to 4 to ensure that "__analyzer_eval" is recognized. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-16analyzer: use known_function to simplify region_model::on_call_{pre,post}David Malcolm1-5/+5
Replace lots of repeated checks against strings with a hash_map lookup. Add some missing type-checking for handling known functions (e.g. checks for pointer types). gcc/analyzer/ChangeLog: * analyzer.h (known_function::matches_call_types_p): New vfunc. (known_function::impl_call_pre): Provide base implementation. (known_function::impl_call_post): New vfunc. (register_known_functions): New. * engine.cc (impl_run_checkers): Call register_known_functions. * region-model-impl-calls.cc (region_model::impl_call_accept): Convert to... (class known_function_accept): ...this. (region_model::impl_call_bind): Convert to... (class known_function_bind): ...this. (region_model::impl_call_connect): Convert to... (class known_function_connect): ...this. (region_model::impl_call_listen): Convert to... (class known_function_listen): ...this. (region_model::impl_call_socket): Convert to... (class known_function_socket): ...this. (register_known_functions): New. * region-model.cc (region_model::on_call_pre): Remove special case for "bind" in favor of the known_function-handling dispatch. Add call to known_function::matches_call_types_p to latter. (region_model::on_call_post): Remove special cases for "accept", "bind", "connect", "listen", and "socket" in favor of dispatch to known_function::impl_call_post. * region-model.h (region_model::impl_call_accept): Delete decl. (region_model::impl_call_bind): Delete decl. (region_model::impl_call_connect): Delete decl. (region_model::impl_call_listen): Delete decl. (region_model::impl_call_socket): Delete decl. * sm-fd.cc: Update comments. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c (copy_across_boundary_fn::matches_call_types_p): New. * gcc.dg/plugin/analyzer_known_fns_plugin.c (known_function_returns_42::matches_call_types_p): New. (known_function_attempt_to_copy::matches_call_types_p): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-15analyzer: add warnings relating to sockets [PR106140]David Malcolm1-16/+1094
This patch generalizes the analyzer's file descriptor state machine so that it tracks the states of sockets. It adds two new warnings relating to misuses of socket APIs: * -Wanalyzer-fd-phase-mismatch (e.g. calling 'accept' on a socket before calling 'listen' on it) * -Wanalyzer-fd-type-mismatch (e.g. using a stream socket operation on a datagram socket) gcc/analyzer/ChangeLog: PR analyzer/106140 * analyzer-language.cc (on_finish_translation_unit): Stash named constants "SOCK_STREAM" and "SOCK_DGRAM". * analyzer.opt (Wanalyzer-fd-phase-mismatch): New. (Wanalyzer-fd-type-mismatch): New. * engine.cc (impl_region_model_context::get_state_map_by_name): Add "out_sm_context" param. Allow out_sm_idx to be NULL. * exploded-graph.h (impl_region_model_context::get_state_map_by_name): Add "out_sm_context" param. * region-model-impl-calls.cc (region_model::impl_call_accept): New. (region_model::impl_call_bind): New. (region_model::impl_call_connect): New. (region_model::impl_call_listen): New. (region_model::impl_call_socket): New. * region-model.cc (region_model::on_call_pre): Special-case "bind". (region_model::on_call_post): Special-case "accept", "bind", "connect", "listen", and "socket". * region-model.h (region_model::impl_call_accept): New decl. (region_model::impl_call_bind): New decl. (region_model::impl_call_connect): New decl. (region_model::impl_call_listen): New decl. (region_model::impl_call_socket): New decl. (region_model::on_socket): New decl. (region_model::on_bind): New decl. (region_model::on_listen): New decl. (region_model::on_accept): New decl. (region_model::on_connect): New decl. (region_model::add_constraint): Make public. (region_model::check_for_poison): Make public. (region_model_context::get_state_map_by_name): Add out_sm_context param. (region_model_context::get_fd_map): Likewise. (region_model_context::get_malloc_map): Likewise. (region_model_context::get_taint_map): Likewise. (noop_region_model_context::get_state_map_by_name): Likewise. (region_model_context_decorator::get_state_map_by_name): Likewise. * sm-fd.cc: Include "analyzer/supergraph.h" and "analyzer/analyzer-language.h". (enum expected_phase): New enum. (fd_state_machine::m_new_datagram_socket): New. (fd_state_machine::m_new_stream_socket): New. (fd_state_machine::m_new_unknown_socket): New. (fd_state_machine::m_bound_datagram_socket): New. (fd_state_machine::m_bound_stream_socket): New. (fd_state_machine::m_bound_unknown_socket): New. (fd_state_machine::m_listening_stream_socket): New. (fd_state_machine::m_m_connected_stream_socket): New. (fd_state_machine::m_SOCK_STREAM): New. (fd_state_machine::m_SOCK_DGRAM): New. (fd_diagnostic::describe_state_change): Handle socket states. (fd_diagnostic::get_meaning_for_state_change): Likewise. (class fd_phase_mismatch): New. (enum expected_type): New enum. (class fd_type_mismatch): New. (fd_state_machine::fd_state_machine): Initialize new states and stashed named constants. (fd_state_machine::is_socket_fd_p): New. (fd_state_machine::is_datagram_socket_fd_p): New. (fd_state_machine::is_stream_socket_fd_p): New. (fd_state_machine::on_close): Handle the socket states. (fd_state_machine::check_for_open_fd): Complain about fncalls on sockets in the wrong phase. Support socket FDs. (add_constraint_ge_zero): New. (fd_state_machine::get_state_for_socket_type): New. (fd_state_machine::on_socket): New. (fd_state_machine::check_for_socket_fd): New. (fd_state_machine::check_for_new_socket_fd): New. (fd_state_machine::on_bind): New. (fd_state_machine::on_listen): New. (fd_state_machine::on_accept): New. (fd_state_machine::on_connect): New. (fd_state_machine::can_purge_p): Don't purge socket values. (get_fd_state): New. (region_model::mark_as_valid_fd): Use get_fd_state. (region_model::on_socket): New. (region_model::on_bind): New. (region_model::on_listen): New. (region_model::on_accept): New. (region_model::on_connect): New. * sm-fd.dot: Update to reflect sm-fd.cc changes. gcc/ChangeLog: PR analyzer/106140 * doc/invoke.texi (Static Analyzer Options): Add -Wanalyzer-fd-phase-mismatch and -Wanalyzer-fd-type-mismatch. Add "socket", "bind", "listen", "accept", and "connect" to the list of functions known to the analyzer. gcc/testsuite/ChangeLog: PR analyzer/106140 * gcc.dg/analyzer/fd-accept.c: New test. * gcc.dg/analyzer/fd-bind.c: New test. * gcc.dg/analyzer/fd-connect.c: New test. * gcc.dg/analyzer/fd-datagram-socket.c: New test. * gcc.dg/analyzer/fd-glibc-byte-stream-connection-server.c: New test. * gcc.dg/analyzer/fd-glibc-byte-stream-socket.c: New test. * gcc.dg/analyzer/fd-glibc-datagram-client.c: New test. * gcc.dg/analyzer/fd-glibc-datagram-socket.c: New test. * gcc.dg/analyzer/fd-glibc-make_named_socket.h: New test. * gcc.dg/analyzer/fd-listen.c: New test. * gcc.dg/analyzer/fd-manpage-getaddrinfo-client.c: New test. * gcc.dg/analyzer/fd-mappage-getaddrinfo-server.c: New test. * gcc.dg/analyzer/fd-socket-meaning.c: New test. * gcc.dg/analyzer/fd-socket-misuse.c: New test. * gcc.dg/analyzer/fd-stream-socket-active-open.c: New test. * gcc.dg/analyzer/fd-stream-socket-passive-open.c: New test. * gcc.dg/analyzer/fd-stream-socket.c: New test. * gcc.dg/analyzer/fd-symbolic-socket.c: New test. * gcc.dg/analyzer/pr104369-1.c: Add -Wno-analyzer-too-complex and -Wno-analyzer-fd-leak to options. * gcc.dg/analyzer/pr104369-2.c: Add -Wno-analyzer-fd-leak to options. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-15c, analyzer: support named constants in analyzer [PR106302]David Malcolm1-10/+20
The analyzer's file-descriptor state machine tracks the access mode of opened files, so that it can emit -Wanalyzer-fd-access-mode-mismatch. To do this, its symbolic execution needs to "know" the values of the constants "O_RDONLY", "O_WRONLY", and "O_ACCMODE". Currently analyzer/sm-fd.cc simply uses these values directly from the build-time header files, but these are the values on the host, not those from the target, which could be different (PR analyzer/106302). In an earlier discussion of this issue: https://gcc.gnu.org/pipermail/gcc/2022-June/238954.html we talked about adding a target hook for this. However, I've also been experimenting with extending the fd state machine to track sockets (PR analyzer/106140). For this, it's useful to "know" the values of the constants "SOCK_STREAM" and "SOCK_DGRAM". Unfortunately, these seem to have many arbitrary differences from target to target. For example: Linux/glibc general has SOCK_STREAM == 1, SOCK_DGRAM == 2, as does AIX, but annoyingly, e.g. Linux on MIPS has them the other way around. It seems to me that as the analyzer grows more ambitious modeling of the behavior of APIs (perhaps via plugins) it's more likely that the analyzer will need to know the values of named constants, which might not even exist on the host. For example, at LPC it was suggested to me that -fanalyzer could check rules about memory management inside the Linux kernel (probably via a plugin), but doing so involves a bunch of GFP_* flags (see PR 107472). So rather than trying to capture all this knowledge in a target hook, this patch attempts to get at named constant values from the user's source code. The patch adds an interface for frontends to call into the analyzer as the translation unit finishes. The analyzer can then call back into the frontend to ask about the values of the named constants it cares about whilst the frontend's data structures are still around. The patch implements this for the C frontend, which looks up the names by looking for named CONST_DECLs (which handles enum values). Failing that, it attempts to look up the values of macros but only the simplest cases are supported (a non-traditional macro with a single CPP_NUMBER token). It does this by building a buffer containing the macro definition and rerunning a lexer on it. The analyzer gracefully handles the cases where named values aren't found (such as anything more complicated than described above). The patch ports the analyzer to use this mechanism for "O_RDONLY", "O_WRONLY", and "O_ACCMODE". I have successfully tested my socket patch to also use this for "SOCK_STREAM" and "SOCK_DGRAM", so the technique seems to work. gcc/ChangeLog: PR analyzer/106302 * Makefile.in (ANALYZER_OBJS): Add analyzer/analyzer-language.o. (GTFILES): Add analyzer/analyzer-language.cc. * doc/analyzer.texi: Document __analyzer_dump_named_constant. gcc/analyzer/ChangeLog: PR analyzer/106302 * analyzer-language.cc: New file. * analyzer-language.h: New file. * analyzer.h (get_stashed_constant_by_name): New decl. (log_stashed_constants): New decl. * engine.cc (impl_run_checkers): Call log_stashed_constants. * region-model-impl-calls.cc (region_model::impl_call_analyzer_dump_named_constant): New. * region-model.cc (region_model::on_stmt_pre): Handle __analyzer_dump_named_constant. * region-model.h (region_model::impl_call_analyzer_dump_named_constant): New decl. * sm-fd.cc (fd_state_machine::m_O_ACCMODE): New. (fd_state_machine::m_O_RDONLY): New. (fd_state_machine::m_O_WRONLY): New. (fd_state_machine::fd_state_machine): Initialize the new fields. (fd_state_machine::get_access_mode_from_flag): Use the new fields, rather than using the host values. gcc/c/ChangeLog: PR analyzer/106302 * c-parser.cc: Include "analyzer/analyzer-language.h" and "toplev.h". (class ana::c_translation_unit): New. (c_parser_translation_unit): Call ana::on_finish_translation_unit. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/analyzer-decls.h (__analyzer_dump_named_constant): New decl. * gcc.dg/analyzer/fd-4.c (void): Likewise. (O_ACCMODE): Define. * gcc.dg/analyzer/fd-access-mode-enum.c: New test, based on . * gcc.dg/analyzer/fd-5.c: ...this. Rename to... * gcc.dg/analyzer/fd-access-mode-macros.c: ...this. (O_ACCMODE): Define. * gcc.dg/analyzer/fd-access-mode-target-headers.c: New test, also based on fd-5.c. (test_sm_fd_constants): New. * gcc.dg/analyzer/fd-dup-1.c (O_ACCMODE): Define. * gcc.dg/analyzer/named-constants-via-enum.c: New test. * gcc.dg/analyzer/named-constants-via-enum-and-macro.c: New test. * gcc.dg/analyzer/named-constants-via-macros-2.c: New test. * gcc.dg/analyzer/named-constants-via-macros.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-03analyzer: use std::unique_ptr for pending_diagnostic/noteDavid Malcolm1-21/+37
gcc/analyzer/ChangeLog: * call-info.cc: Add define of INCLUDE_MEMORY. * call-summary.cc: Likewise. * checker-path.cc: Likewise. * constraint-manager.cc: Likewise. * diagnostic-manager.cc: Likewise. (saved_diagnostic::saved_diagnostic): Use std::unique_ptr for param d and field m_d. (saved_diagnostic::~saved_diagnostic): Remove explicit delete of m_d. (saved_diagnostic::add_note): Use std::unique_ptr for param pn. (saved_diagnostic::get_pending_diagnostic): Update for conversion of m_sd.m_d to unique_ptr. (diagnostic_manager::add_diagnostic): Use std::unique_ptr for param d. Remove explicit deletion. (diagnostic_manager::add_note): Use std::unique_ptr for param pn. (diagnostic_manager::emit_saved_diagnostic): Update for conversion of m_sd.m_d to unique_ptr. (null_assignment_sm_context::warn): Use std::unique_ptr for param d. Remove explicit deletion. * diagnostic-manager.h (saved_diagnostic::saved_diagnostic): Use std::unique_ptr for param d. (saved_diagnostic::add_note): Likewise for param pn. (saved_diagnostic::m_d): Likewise. (diagnostic_manager::add_diagnostic): Use std::unique_ptr for param d. (diagnostic_manager::add_note): Use std::unique_ptr for param pn. * engine.cc: Include "make-unique.h". (impl_region_model_context::warn): Update to use std::unique_ptr for param, removing explicit deletion. (impl_region_model_context::add_note): Likewise. (impl_sm_context::warn): Update to use std::unique_ptr for param. (impl_region_model_context::on_state_leak): Likewise for result of on_leak. (exploded_node::on_longjmp): Use make_unique when creating pending_diagnostic. (exploded_graph::process_node): Likewise. * exploded-graph.h (impl_region_model_context::warn): Update to use std::unique_ptr for param. (impl_region_model_context::add_note): Likewise. * feasible-graph.cc: Add define of INCLUDE_MEMORY. * pending-diagnostic.cc: Likewise. * pending-diagnostic.h: Include analyzer.sm.h" * program-point.cc: Add define of INCLUDE_MEMORY. * program-state.cc: Likewise. * region-model-asm.cc: Likewise. * region-model-impl-calls.cc: Likewise. Include "make-unique.h". (region_model::impl_call_putenv): Use make_unique when creating pending_diagnostic. * region-model-manager.cc: Add define of INCLUDE_MEMORY. * region-model-reachability.cc: Likewise. * region-model.cc: Likewise. Include "make-unique.h". (region_model::get_gassign_result): Use make_unique when creating pending_diagnostic. (region_model::check_for_poison): Likewise. (region_model::on_stmt_pre): Likewise. (region_model::check_symbolic_bounds): Likewise. (region_model::check_region_bounds): Likewise. (annotating_ctxt: make_note): Use std::unique_ptr for result. (region_model::deref_rvalue): Use make_unique when creating pending_diagnostic. (region_model::check_for_writable_region): Likewise. (region_model::check_region_size): Likewise. (region_model::check_dynamic_size_for_floats): Likewise. (region_model::maybe_complain_about_infoleak): Likewise. (noop_region_model_context::add_note): Use std::unique_ptr for param. Remove explicit deletion. * region-model.h: Include "analyzer/pending-diagnostic.h". (region_model_context::warn): Convert param to std::unique_ptr. (region_model_context::add_note): Likewise. (noop_region_model_context::warn): Likewise. (noop_region_model_context::add_note): Likewise. (region_model_context_decorator::warn): Likewise. (region_model_context_decorator::add_note): Likewise. (note_adding_context::warn): Likewise. (note_adding_context::make_note): Likewise for return type. (test_region_model_context::warn): Convert param to std::unique_ptr. * region.cc: Add define of INCLUDE_MEMORY. * sm-fd.cc: Likewise. Include "make-unique.h". (fd_state_machine::check_for_fd_attrs): Use make_unique when creating pending_diagnostics. (fd_state_machine::on_open): Likewise. (fd_state_machine::on_creat): Likewise. (fd_state_machine::check_for_dup): Likewise. (fd_state_machine::on_close): Likewise. (fd_state_machine::check_for_open_fd): Likewise. (fd_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. * sm-file.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (fileptr_state_machine::on_stmt): Use make_unique when creating pending_diagnostic. (fileptr_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. * sm-malloc.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (malloc_state_machine::on_stmt): Use make_unique when creating pending_diagnostic. (malloc_state_machine::handle_free_of_non_heap): Likewise. (malloc_state_machine::on_deallocator_call): Likewise. (malloc_state_machine::on_realloc_call): Likewise. (malloc_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. * sm-pattern-test.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (pattern_test_state_machine::on_condition): Use make_unique when creating pending_diagnostic. * sm-sensitive.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (sensitive_state_machine::warn_for_any_exposure): Use make_unique when creating pending_diagnostic. * sm-signal.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (signal_state_machine::on_stmt): Use make_unique when creating pending_diagnostic. * sm-taint.cc: Add define of INCLUDE_MEMORY. Include "make-unique.h". (taint_state_machine::check_for_tainted_size_arg): Use make_unique when creating pending_diagnostic. (taint_state_machine::check_for_tainted_divisor): Likewise. (region_model::check_region_for_taint): Likewise. (region_model::check_dynamic_size_for_taint): Likewise. * sm.cc: Add define of INCLUDE_MEMORY. Include "analyzer/pending-diagnostic.h". (state_machine::on_leak): Move here from sm.h, changing return type to std::unique_ptr. * sm.h (state_machine::on_leak): Change return type to std::unique_ptr. Move defn of base impl to sm.cc (sm_context::warn): Convert param d to std_unique_ptr. * state-purge.cc: Add define of INCLUDE_MEMORY. * store.cc: Likewise. * svalue.cc: Likewise. * trimmed-graph.cc: Likewise. * varargs.cc: Likewise. Include "make-unique.h". (va_list_state_machine::check_for_ended_va_list): Use make_unique when creating pending_diagnostic. (va_list_state_machine::on_leak): Likewise, converting return type to std::unique_ptr. (region_model::impl_call_va_arg): Use make_unique when creating pending_diagnostic. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: Add define of INCLUDE_MEMORY. Include "make-unique.h". (gil_state_machine::check_for_pyobject_in_call): Use make_unique when creating pending_diagnostic. (gil_state_machine::on_stmt): Likewise. (gil_state_machine::check_for_pyobject_usage_without_gil): Likewise. * gcc.dg/plugin/analyzer_kernel_plugin.c: : Add define of INCLUDE_MEMORY. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-10-26analyzer: fixes to file-descriptor handlingDavid Malcolm1-17/+17
gcc/analyzer/ChangeLog: * sm-fd.cc (fd_state_machine::on_open): Transition to "unchecked" when the mode is symbolic, rather than just on integer constants. (fd_state_machine::check_for_open_fd): Don't complain about unchecked values in the start state. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fd-3.c (test_5): Expect "opened here" message even when flags are symbolic. (test_read_from_symbolic_fd): New. (test_write_to_symbolic_fd): New. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-10-24analyzer: handle "pipe" and "pipe2" [PR106300]David Malcolm1-4/+52
gcc/analyzer/ChangeLog: PR analyzer/106300 * engine.cc (impl_region_model_context::get_fd_map): New. * exploded-graph.h (impl_region_model_context::get_fd_map): New decl. * region-model-impl-calls.cc (region_model::impl_call_pipe): New. * region-model.cc (region_model::update_for_int_cst_return): New, based on... (region_model::update_for_zero_return): ...this. Reimplement in terms of the former. (region_model::on_call_pre): Handle "pipe" and "pipe2". (region_model::on_call_post): Likewise. * region-model.h (region_model::impl_call_pipe): New decl. (region_model::update_for_int_cst_return): New decl. (region_model::mark_as_valid_fd): New decl. (region_model_context::get_fd_map): New pure virtual fn. (noop_region_model_context::get_fd_map): New. (region_model_context_decorator::get_fd_map): New. * sm-fd.cc: Include "analyzer/program-state.h". (fd_state_machine::describe_state_change): Handle transitions from start state to valid states. (fd_state_machine::mark_as_valid_fd): New. (fd_state_machine::on_stmt): Add missing return for "creat". (region_model::mark_as_valid_fd): New. gcc/ChangeLog: PR analyzer/106300 * doc/invoke.texi (Static Analyzer Options): Add "pipe" and "pipe2" to the list of functions the analyzer has hardcoded knowledge of. gcc/testsuite/ChangeLog: PR analyzer/106300 * gcc.dg/analyzer/pipe-1.c: New test. * gcc.dg/analyzer/pipe-glibc.c: New test. * gcc.dg/analyzer/pipe-manpages.c: New test. * gcc.dg/analyzer/pipe2-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-10-05analyzer: simplify some includesDavid Malcolm1-4/+0
gcc/analyzer/ChangeLog: * analysis-plan.cc: Simplify includes. * analyzer-pass.cc: Likewise. * analyzer-selftests.cc: Likewise. * analyzer.cc: Likewise. * analyzer.h: Add includes of "json.h" and "tristate.h". * call-info.cc: Simplify includes. * call-string.cc: Likewise. * call-summary.cc: Likewise. * checker-path.cc: Likewise. * complexity.cc: Likewise. * constraint-manager.cc: Likewise. * diagnostic-manager.cc: Likewise. * engine.cc: Likewise. * feasible-graph.cc: Likewise. * known-function-manager.cc: Likewise. * pending-diagnostic.cc: Likewise. * program-point.cc: Likewise. * program-state.cc: Likewise. * region-model-asm.cc: Likewise. * region-model-impl-calls.cc: Likewise. * region-model-manager.cc: Likewise. * region-model-reachability.cc: Likewise. * region-model.cc: Likewise. * region-model.h: Include "selftest.h". * region.cc: Simplify includes. * sm-fd.cc: Likewise. * 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. * sm.cc: Likewise. * state-purge.cc: Likewise. * store.cc: Likewise. * store.h: Likewise. * supergraph.cc: Likewise. * svalue.cc: Likewise. * svalue.h: Likewise. * trimmed-graph.cc: Likewise. * varargs.cc: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-08-15analyzer: fix for ICE in sm-fd.cc [PR106551]Immad Mir1-2/+1
This patch fixes the ICE caused by valid_to_unchecked_state in sm-fd.cc by exiting early if first argument of any "dup" functions is invalid. gcc/analyzer/ChangeLog: PR analyzer/106551 * sm-fd.cc (check_for_dup): exit early if first argument is invalid for all dup functions. gcc/testsuite/ChangeLog: PR analyzer/106551 * gcc.dg/analyzer/fd-dup-1.c: New testcase. Signed-off-by: Immad Mir <mirimmad@outlook.com>
2022-08-11analyzer: fix ICE casued by dup2 in sm-fd.cc[PR106551]Immad Mir1-4/+6
This patch fixes the ICE caused by valid_to_unchecked_state, at analyzer/sm-fd.cc by handling the m_start state in check_for_dup. Tested lightly on x86_64. gcc/analyzer/ChangeLog: PR analyzer/106551 * sm-fd.cc (check_for_dup): handle the m_start state when transitioning the state of LHS of dup, dup2 and dup3 call. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fd-dup-1.c: New testcases. * gcc.dg/analyzer/fd-uninit-1.c: Remove bogus warning. Signed-off-by: Immad Mir <mirimmad@outlook.com>
2022-08-02analyzer: support for creat, dup, dup2 and dup3 [PR106298]Immad Mir1-3/+126
This patch extends the state machine in sm-fd.cc to support creat, dup, dup2 and dup3 functions. Lightly tested on x86_64 Linux. gcc/analyzer/ChangeLog: PR analyzer/106298 * sm-fd.cc (fd_state_machine::on_open): Add creat, dup, dup2 and dup3 functions. (enum dup): New. (fd_state_machine::valid_to_unchecked_state): New. (fd_state_machine::on_creat): New. (fd_state_machine::on_dup): New. gcc/testsuite/ChangeLog: PR analyzer/106298 * gcc.dg/analyzer/fd-1.c: Add tests for 'creat'. * gcc.dg/analyzer/fd-2.c: Likewise. * gcc.dg/analyzer/fd-4.c: Likewise. * gcc.dg/analyzer/fd-dup-1.c: New tests. Signed-off-by: Immad Mir <mirimmad@outlook.com>
2022-07-27analyzer: add get_meaning_for_state_change vfunc to fd_diagnostic in ↵Immad Mir1-0/+14
sm-fd.cc [PR106286] This patch adds get_meaning_for_state_change vfunc to fd_diagnostic in sm-fd.cc which could be used by SARIF output. Lightly tested on x86_64 Linux. gcc/analyzer/ChangeLog: PR analyzer/106286 * sm-fd.cc: (fd_diagnostic::get_meaning_for_state_change): New. gcc/testsuite/ChangeLog: PR analyzer/106286 * gcc.dg/analyzer/fd-meaning.c: New test. Signed-off-by: Immad Mir <mirimmad@outlook.com>
2022-07-25analyzer: fix coding style in sm-fd.ccMartin Liska1-1057/+1057
gcc/analyzer/ChangeLog: * sm-fd.cc: Run dos2unix and fix coding style issues.
2022-07-23Adding three new function attributes for static analysis of file descriptorsImmad Mir1-69/+269
This patch adds three new function attributes to GCC that are used for static analysis of usage of file descriptors: 1) __attribute__ ((fd_arg(N))): The attributes may be applied to a function that takes an open file descriptor at refrenced argument N. It indicates that the passed filedescriptor must not have been closed. Therefore, when the analyzer is enabled with -fanalyzer, the analyzer may emit a -Wanalyzer-fd-use-after-close diagnostic if it detects a code path in which a function with this attribute is called with a closed file descriptor. The attribute also indicates that the file descriptor must have been checked for validity before usage. Therefore, analyzer may emit -Wanalyzer-fd-use-without-check diagnostic if it detects a code path in which a function with this attribute is called with a file descriptor that has not been checked for validity. 2) __attribute__((fd_arg_read(N))): The attribute is identical to fd_arg, but with the additional requirement that it might read from the file descriptor, and thus, the file descriptor must not have been opened as write-only. The analyzer may emit a -Wanalyzer-access-mode-mismatch diagnostic if it detects a code path in which a function with this attribute is called on a file descriptor opened with O_WRONLY. 3) __attribute__((fd_arg_write(N))): The attribute is identical to fd_arg_read except that the analyzer may emit a -Wanalyzer-access-mode-mismatch diagnostic if it detects a code path in which a function with this attribute is called on a file descriptor opened with O_RDONLY. gcc/analyzer/ChangeLog: * sm-fd.cc (fd_param_diagnostic): New diagnostic class. (fd_access_mode_mismatch): Change inheritance from fd_diagnostic to fd_param_diagnostic. Add new overloaded constructor. (fd_use_after_close): Likewise. (unchecked_use_of_fd): Likewise and also change name to fd_use_without_check. (double_close): Change name to fd_double_close. (enum access_directions): New. (fd_state_machine::on_stmt): Handle calls to function with the new three function attributes. (fd_state_machine::check_for_fd_attrs): New. (fd_state_machine::on_open): Use the new overloaded constructors of diagnostic classes. gcc/c-family/ChangeLog: * c-attribs.cc: (c_common_attribute_table): add three new attributes namely: fd_arg, fd_arg_read and fd_arg_write. (handle_fd_arg_attribute): New. gcc/ChangeLog: * doc/extend.texi: Add fd_arg, fd_arg_read and fd_arg_write under "Common Function Attributes" section. * doc/invoke.texi: Add docs to -Wanalyzer-fd-access-mode-mismatch, -Wanalyzer-use-after-close, -Wanalyzer-fd-use-without-check that these warnings may be emitted through usage of three function attributes used for static analysis of file descriptors namely fd_arg, fd_arg_read and fd_arg_write. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fd-5.c: New test. * gcc.dg/analyzer/fd-4.c: Remove quotes around 'read-only' and 'write-only'. * c-c++-common/attr-fd.c: New test. Signed-off-by: Immad Mir <mirimmad17@gmail.com>
2022-07-06analyzer: reorder initialization of state m_invalid in sm-fd.cc [PR106184]Immad Mir1-2/+3
This patch reorders the initialization of state m_invalid in sm-fd.cc so that the order of initializers is same as the ordering of the fields in the class decl. gcc/analyzer/ChangeLog: PR analyzer/106184 * sm-fd.cc (fd_state_machine): Change ordering of initialization of state m_invalid so that the order of initializers is same as the ordering of the fields in the class decl. Signed-off-by: Immad Mir <mirimmad@outlook.com>
2022-07-06analyzer: show close event for use_after_close diagnosticImmad Mir1-3/+12
This patch saves the "close" event in use_after_close diagnostic and shows it where possible. gcc/analyzer/ChangeLog: * sm-fd.cc (use_after_close): save the "close" event and show it where possible. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fd-4.c (test_3): change the message note to conform to the changes in analyzer/sm-fd.cc (test_4): Likewise. Signed-off-by: Immad Mir <mirimmad@outlook.com>
2022-07-02analyzer: implement five new warnings for misuse of POSIX file descriptor ↵Immad Mir1-0/+847
APIs [PR106003]. This patch adds a new state machine to the analyzer for checking usage of POSIX file descriptor APIs with five new warnings. It adds: - check for FD leaks (CWE 775). - check for double "close" of a FD (CWE-1341). - check for read/write of a closed file descriptor. - check whether a file descriptor was used without being checked for validity. - check for read/write of a descriptor opened for just writing/reading. gcc/ChangeLog: PR analyzer/106003 * Makefile.in (ANALYZER_OBJS): Add sm-fd.o. * doc/invoke.texi: Add -Wanalyzer-fd-double-close, -Wanalyzer-fd-leak, -Wanalyzer-fd-access-mode-mismatch, -Wanalyzer-fd-use-without-check, -Wanalyzer-fd-use-after-close. gcc/analyzer/ChangeLog: PR analyzer/106003 * analyzer.opt (Wanalyzer-fd-leak): New option. (Wanalyzer-fd-access-mode-mismatch): New option. (Wanalyzer-fd-use-without-check): New option. (Wanalyzer-fd-double-close): New option. (Wanalyzer-fd-use-after-close): New option. * sm.h (make_fd_state_machine): New decl. * sm.cc (make_checkers): Call make_fd_state_machine. * sm-fd.cc: New file. gcc/testsuite/ChangeLog: PR analyzer/106003 * gcc.dg/analyzer/fd-1.c: New test. * gcc.dg/analyzer/fd-2.c: New test. * gcc.dg/analyzer/fd-3.c: New test. * gcc.dg/analyzer/fd-4.c: New test.