aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/plugin
AgeCommit message (Collapse)AuthorFilesLines
2023-08-30analyzer: implement reference count checking for CPython plugin [PR107646]Eric Feng6-32/+491
This patch introduces initial support for reference count checking of PyObjects in relation to the Python/C API for the CPython plugin. Additionally, the core analyzer underwent several modifications to accommodate this feature. These include: - Introducing support for callbacks at the end of region_model::pop_frame. This is our current point of validation for the reference count of PyObjects. - An added optional custom stmt_finder parameter to region_model_context::warn. This aids in emitting a diagnostic concerning the reference count, especially when the stmt_finder is NULL, which is currently the case during region_model::pop_frame. The current diagnostic we emit relating to the reference count appears as follows: rc3.c:23:10: warning: expected ‘item’ to have reference count: ‘1’ but ob_refcnt field is: ‘2’ 23 | return list; | ^~~~ ‘create_py_object’: events 1-4 | | 4 | PyObject* item = PyLong_FromLong(3); | | ^~~~~~~~~~~~~~~~~~ | | | | | (1) when ‘PyLong_FromLong’ succeeds | 5 | PyObject* list = PyList_New(1); | | ~~~~~~~~~~~~~ | | | | | (2) when ‘PyList_New’ succeeds |...... | 14 | PyList_Append(list, item); | | ~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (3) when ‘PyList_Append’ succeeds, moving buffer |...... | 23 | return list; | | ~~~~ | | | | | (4) here | This is a WIP in several ways: - Currently, functions returning PyObject * are assumed to always produce a new reference. - The validation of reference count is only for PyObjects created within a function body. Verifying reference counts for PyObjects passed as parameters is not supported in this patch. gcc/analyzer/ChangeLog: PR analyzer/107646 * engine.cc (impl_region_model_context::warn): New optional parameter. * exploded-graph.h (class impl_region_model_context): Likewise. * region-model.cc (region_model::pop_frame): New callback feature for region_model::pop_frame. * region-model.h (struct append_regions_cb_data): Likewise. (class region_model): Likewise. (class region_model_context): New optional parameter. (class region_model_context_decorator): Likewise. gcc/testsuite/ChangeLog: PR analyzer/107646 * gcc.dg/plugin/analyzer_cpython_plugin.c: Implements reference count checking for PyObjects. * gcc.dg/plugin/cpython-plugin-test-2.c: Moved to... * gcc.dg/plugin/cpython-plugin-test-PyList_Append.c: ...here (and added more tests). * gcc.dg/plugin/cpython-plugin-test-1.c: Moved to... * gcc.dg/plugin/cpython-plugin-test-no-Python-h.c: ...here (and added more tests). * gcc.dg/plugin/plugin.exp: New tests. * gcc.dg/plugin/cpython-plugin-test-PyList_New.c: New test. * gcc.dg/plugin/cpython-plugin-test-PyLong_FromLong.c: New test. Signed-off-by: Eric Feng <ef2648@columbia.edu>
2023-08-20Testsuite, darwin: Fix analyzer testcasesFrancois-Xavier Coudert3-0/+9
On darwin, system headers are fortified by default and that defeats the analyzer's warnings on memcpy() calls. Turn this off for testing. gcc/testsuite/ChangeLog: * gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c: Use _FORTIFY_SOURCE=0 on darwin. * gcc.dg/plugin/taint-CVE-2011-0521-5.c: Likewise. * gcc.dg/plugin/taint-CVE-2011-0521-6.c: Likewise.
2023-08-20Testsuite, plugin: make testcase pattern more flexibleFrancois-Xavier Coudert1-1/+1
On Darwin, the message recorded in the sarif file contains: "message": {"text": "Segmentation fault: 11"} which is different from, e.g., linux: "message": {"text": "Segmentation fault"} Adjusting the testcase pattern to be a little more flexible. gcc/testsuite/ChangeLog: * gcc.dg/plugin/crash-test-write-though-null-sarif.c: Update expected pattern.
2023-08-11analyzer: More features for CPython analyzer plugin [PR107646]Eric Feng3-1/+802
This patch adds known function subclasses for Python/C API functions PyList_New, PyLong_FromLong, and PyList_Append. It also adds new optional parameters for region_model::get_or_create_region_for_heap_alloc, allowing for the newly allocated region to immediately transition from the start state to the assumed non-null state in the malloc state machine if desired. Finally, it adds a new procedure, dg-require-python-h, intended as a directive in Python-related analyzer tests, to append necessary Python flags during the tests' build process. The main warnings we gain in this patch with respect to the known function subclasses mentioned are leak related. For example: rc3.c: In function ‘create_py_object’: │ rc3.c:21:10: warning: leak of ‘item’ [CWE-401] [-Wanalyzer-malloc-leak] │ 21 | return list; │ | ^~~~ │ ‘create_py_object’: events 1-4 │ | │ | 4 | PyObject* item = PyLong_FromLong(10); │ | | ^~~~~~~~~~~~~~~~~~~ │ | | | │ | | (1) allocated here │ | | (2) when ‘PyLong_FromLong’ succeeds │ | 5 | PyObject* list = PyList_New(2); │ | | ~~~~~~~~~~~~~ │ | | | │ | | (3) when ‘PyList_New’ fails │ |...... │ | 21 | return list; │ | | ~~~~ │ | | | │ | | (4) ‘item’ leaks here; was allocated at (1) │ Some concessions were made to simplify the analysis process when comparing kf_PyList_Append with the real implementation. In particular, PyList_Append performs some optimization internally to try and avoid calls to realloc if possible. For simplicity, we assume that realloc is called every time. Also, we grow the size by just 1 (to ensure enough space for adding a new element) rather than abide by the heuristics that the actual implementation follows. gcc/analyzer/ChangeLog: PR analyzer/107646 * call-details.h: New function. * region-model.cc (region_model::get_or_create_region_for_heap_alloc): New optional parameters. * region-model.h (class region_model): New optional parameters. * sm-malloc.cc (on_realloc_with_move): New function. (region_model::transition_ptr_sval_non_null): New function. gcc/testsuite/ChangeLog: PR analyzer/107646 * gcc.dg/plugin/analyzer_cpython_plugin.c: Analyzer support for PyList_New, PyList_Append, PyLong_FromLong * gcc.dg/plugin/plugin.exp: New test. * lib/target-supports.exp: New procedure. * gcc.dg/plugin/cpython-plugin-test-2.c: New test. Signed-off-by: Eric Feng <ef2648@columbia.edu>
2023-08-09analyzer: remove default return value from region_model::on_call_preDavid Malcolm2-4/+10
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-08-03poly_int: Handle more can_div_trunc_p casesRichard Sandiford1-11/+74
can_div_trunc_p (a, b, &Q, &r) tries to compute a Q and r that satisfy the usual conditions for truncating division: (1) a = b * Q + r (2) |b * Q| <= |a| (3) |r| < |b| We can compute Q using the constant component (the case when all indeterminates are zero). Since |r| < |b| for the constant case, the requirements for indeterminate xi with coefficients ai (for a) and bi (for b) are: (2') |bi * Q| <= |ai| (3') |ai - bi * Q| <= |bi| (See the big comment for more details, restrictions, and reasoning). However, the function works on abstract arithmetic types, and so it has to be careful not to introduce new overflow. The code therefore only handled the extreme for (3'), that is: |ai - bi * Q| = |bi| for the case where Q is zero. Looking at it again, the overflow issue is a bit easier to handle than I'd originally thought (or so I hope). This patch therefore extends the code to handle |ai - bi * Q| = |bi| for all Q, with Q = 0 no longer being a separate case. The net effect is to allow the function to succeed for things like: (a0 + b1 (Q+1) x) / (b0 + b1 x) where Q = a0 / b0, with various sign conditions. E.g. we now handle: (7 + 8x) / (4 + 4x) with Q = 1 and r = 3 + 4x, gcc/ * poly-int.h (can_div_trunc_p): Succeed for more boundary conditions. gcc/testsuite/ * gcc.dg/plugin/poly-int-tests.h (test_can_div_trunc_p_const) (test_can_div_trunc_p_const): Add more tests.
2023-08-02analyzer: stash values for CPython plugin [PR107646]Eric Feng3-0/+240
This patch adds a hook to the end of ana::on_finish_translation_unit which calls relevant stashing-related callbacks registered during plugin initialization. This feature is used to stash named types and global variables for a CPython analyzer plugin [PR107646]. gcc/analyzer/ChangeLog: PR analyzer/107646 * analyzer-language.cc (run_callbacks): New function. (on_finish_translation_unit): New function. * analyzer-language.h (GCC_ANALYZER_LANGUAGE_H): New include. (class translation_unit): New vfuncs. gcc/c/ChangeLog: PR analyzer/107646 * c-parser.cc: New functions on stashing values for the analyzer. gcc/testsuite/ChangeLog: PR analyzer/107646 * gcc.dg/plugin/plugin.exp: Add new plugin and test. * gcc.dg/plugin/analyzer_cpython_plugin.c: New plugin. * gcc.dg/plugin/cpython-plugin-test-1.c: New test. Signed-off-by: Eric Feng <ef2648@columbia.edu>
2023-06-29testsuite: Use -fno-report-bug in gcc.dg/plugin/Marek Polacek4-2/+6
Certain downstream compilers (for example, in Fedora) default to -freport-bug. The extra output breaks the following tests. We can use -fno-report-bug to fix that. Patch verified with: $ make check RUNTESTFLAGS='--target_board=unix\{,-freport-bug\} plugin.exp' gcc/testsuite/ChangeLog: * gcc.dg/plugin/crash-test-ice-sarif.c: Use -fno-report-bug. Adjust scan-sarif-file. * gcc.dg/plugin/crash-test-ice-stderr.c: Use -fno-report-bug. * gcc.dg/plugin/crash-test-write-though-null-sarif.c: Use -fno-report-bug. Adjust scan-sarif-file. * gcc.dg/plugin/crash-test-write-though-null-stderr.c: Use -fno-report-bug.
2023-06-23text-art: remove explicit #include of C++ standard library headersDavid Malcolm1-0/+1
gcc/analyzer/ChangeLog: * access-diagram.cc: Add #define INCLUDE_VECTOR. * bounds-checking.cc: Likewise. gcc/ChangeLog: * diagnostic-format-sarif.cc: Add #define INCLUDE_VECTOR. * diagnostic.cc: Likewise. * text-art/box-drawing.cc: Likewise. * text-art/canvas.cc: Likewise. * text-art/ruler.cc: Likewise. * text-art/selftests.cc: Likewise. * text-art/selftests.h (text_art::canvas): New forward decl. * text-art/style.cc: Add #define INCLUDE_VECTOR. * text-art/styled-string.cc: Likewise. * text-art/table.cc: Likewise. * text-art/table.h: Remove #include <vector>. * text-art/theme.cc: Add #define INCLUDE_VECTOR. * text-art/types.h: Check that INCLUDE_VECTOR is defined. Remove #include of <vector> and <string>. * text-art/widget.cc: Add #define INCLUDE_VECTOR. * text-art/widget.h: Remove #include <vector>. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic_plugin_test_text_art.c: Add #define INCLUDE_VECTOR. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-06-21analyzer: add text-art visualizations of out-of-bounds accesses [PR106626]David Malcolm1-3/+3
This patch extends -Wanalyzer-out-of-bounds so that, where possible, it will emit a text art diagram visualizing the spatial relationship between (a) the memory region that the analyzer predicts would be accessed, versus (b) the range of memory that is valid to access - whether they overlap, are touching, are close or far apart; which one is before or after in memory, the relative sizes involved, the direction of the access (read vs write), and, in some cases, the values of data involved. This diagram can be suppressed using -fdiagnostics-text-art-charset=none. For example, given: int32_t arr[10]; int32_t int_arr_read_element_before_start_far(void) { return arr[-100]; } it emits: demo-1.c: In function ‘int_arr_read_element_before_start_far’: demo-1.c:7:13: warning: buffer under-read [CWE-127] [-Wanalyzer-out-of-bounds] 7 | return arr[-100]; | ~~~^~~~~~ ‘int_arr_read_element_before_start_far’: event 1 | | 7 | return arr[-100]; | | ~~~^~~~~~ | | | | | (1) out-of-bounds read from byte -400 till byte -397 but ‘arr’ starts at byte 0 | demo-1.c:7:13: note: valid subscripts for ‘arr’ are ‘[0]’ to ‘[9]’ ┌───────────────────────────┐ │read of ‘int32_t’ (4 bytes)│ └───────────────────────────┘ ^ │ │ ┌───────────────────────────┐ ┌────────┬────────┬─────────┐ │ │ │ [0] │ ... │ [9] │ │ before valid range │ ├────────┴────────┴─────────┤ │ │ │‘arr’ (type: ‘int32_t[10]’)│ └───────────────────────────┘ └───────────────────────────┘ ├─────────────┬─────────────┤├─────┬──────┤├─────────────┬─────────────┤ │ │ │ ╭────────────┴───────────╮ ╭────┴────╮ ╭───────┴──────╮ │⚠️ under-read of 4 bytes│ │396 bytes│ │size: 40 bytes│ ╰────────────────────────╯ ╰─────────╯ ╰──────────────╯ and given: #include <string.h> void test_non_ascii () { char buf[5]; strcpy (buf, "文字化け"); } it emits: demo-2.c: In function ‘test_non_ascii’: demo-2.c:7:3: warning: stack-based buffer overflow [CWE-121] [-Wanalyzer-out-of-bounds] 7 | strcpy (buf, "文字化け"); | ^~~~~~~~~~~~~~~~~~~~~~~~ ‘test_non_ascii’: events 1-2 | | 6 | char buf[5]; | | ^~~ | | | | | (1) capacity: 5 bytes | 7 | strcpy (buf, "文字化け"); | | ~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) out-of-bounds write from byte 5 till byte 12 but ‘buf’ ends at byte 5 | demo-2.c:7:3: note: write of 8 bytes to beyond the end of ‘buf’ 7 | strcpy (buf, "文字化け"); | ^~~~~~~~~~~~~~~~~~~~~~~~ demo-2.c:7:3: note: valid subscripts for ‘buf’ are ‘[0]’ to ‘[4]’ ┌─────┬─────┬─────┬────┬────┐┌────┬────┬────┬────┬────┬────┬────┬──────┐ │ [0] │ [1] │ [2] │[3] │[4] ││[5] │[6] │[7] │[8] │[9] │[10]│[11]│ [12] │ ├─────┼─────┼─────┼────┼────┤├────┼────┼────┼────┼────┼────┼────┼──────┤ │0xe6 │0x96 │0x87 │0xe5│0xad││0x97│0xe5│0x8c│0x96│0xe3│0x81│0x91│ 0x00 │ ├─────┴─────┴─────┼────┴────┴┴────┼────┴────┴────┼────┴────┴────┼──────┤ │ U+6587 │ U+5b57 │ U+5316 │ U+3051 │U+0000│ ├─────────────────┼───────────────┼──────────────┼──────────────┼──────┤ │ 文 │ 字 │ 化 │ け │ NUL │ ├─────────────────┴───────────────┴──────────────┴──────────────┴──────┤ │ string literal (type: ‘char[13]’) │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ v v v v v v v v v v v v v ┌─────┬────────────────┬────┐┌─────────────────────────────────────────┐ │ [0] │ ... │[4] ││ │ ├─────┴────────────────┴────┤│ after valid range │ │ ‘buf’ (type: ‘char[5]’) ││ │ └───────────────────────────┘└─────────────────────────────────────────┘ ├─────────────┬─────────────┤├────────────────────┬────────────────────┤ │ │ ╭────────┴────────╮ ╭───────────┴──────────╮ │capacity: 5 bytes│ │⚠️ overflow of 8 bytes│ ╰─────────────────╯ ╰──────────────────────╯ showing that the overflow occurs partway through the UTF-8 encoding of the U+5b57 code point. There are lots more examples in the test suite. It doesn't show up in this email, but the above diagrams are colorized to constrast the valid and invalid access ranges. gcc/ChangeLog: PR analyzer/106626 * Makefile.in (ANALYZER_OBJS): Add analyzer/access-diagram.o. * doc/invoke.texi (Wanalyzer-out-of-bounds): Add description of text art. (fanalyzer-debug-text-art): New. gcc/analyzer/ChangeLog: PR analyzer/106626 * access-diagram.cc: New file. * access-diagram.h: New file. * analyzer.h (class region_offset): Add default ctor. (region_offset::make_byte_offset): New decl. (region_offset::concrete_p): New. (region_offset::get_concrete_byte_offset): New. (region_offset::calc_symbolic_bit_offset): New decl. (region_offset::calc_symbolic_byte_offset): New decl. (region_offset::dump_to_pp): New decl. (region_offset::dump): New decl. (operator<, operator<=, operator>, operator>=): New decls for region_offset. * analyzer.opt (-param=analyzer-text-art-string-ellipsis-threshold=): New. (-param=analyzer-text-art-string-ellipsis-head-len=): New. (-param=analyzer-text-art-string-ellipsis-tail-len=): New. (-param=analyzer-text-art-ideal-canvas-width=): New. (fanalyzer-debug-text-art): New. * bounds-checking.cc: Include "intl.h", "diagnostic-diagram.h", and "analyzer/access-diagram.h". (class out_of_bounds::oob_region_creation_event_capacity): New. (out_of_bounds::out_of_bounds): Add "model" and "sval_hint" params. (out_of_bounds::mark_interesting_stuff): Use the base region. (out_of_bounds::add_region_creation_events): Use oob_region_creation_event_capacity. (out_of_bounds::get_dir): New pure vfunc. (out_of_bounds::maybe_show_notes): New. (out_of_bounds::maybe_show_diagram): New. (out_of_bounds::make_access_diagram): New. (out_of_bounds::m_model): New field. (out_of_bounds::m_sval_hint): New field. (out_of_bounds::m_region_creation_event_id): New field. (concrete_out_of_bounds::concrete_out_of_bounds): Update for new fields. (concrete_past_the_end::concrete_past_the_end): Likewise. (concrete_past_the_end::add_region_creation_events): Use oob_region_creation_event_capacity. (concrete_buffer_overflow::concrete_buffer_overflow): Update for new fields. (concrete_buffer_overflow::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_overflow::get_dir): New. (concrete_buffer_over_read::concrete_buffer_over_read): Update for new fields. (concrete_buffer_over_read::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_overflow::get_dir): New. (concrete_buffer_underwrite::concrete_buffer_underwrite): Update for new fields. (concrete_buffer_underwrite::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_underwrite::get_dir): New. (concrete_buffer_under_read::concrete_buffer_under_read): Update for new fields. (concrete_buffer_under_read::emit): Replace call to maybe_describe_array_bounds with maybe_show_notes. (concrete_buffer_under_read::get_dir): New. (symbolic_past_the_end::symbolic_past_the_end): Update for new fields. (symbolic_buffer_overflow::symbolic_buffer_overflow): Likewise. (symbolic_buffer_overflow::emit): Call maybe_show_notes. (symbolic_buffer_overflow::get_dir): New. (symbolic_buffer_over_read::symbolic_buffer_over_read): Update for new fields. (symbolic_buffer_over_read::emit): Call maybe_show_notes. (symbolic_buffer_over_read::get_dir): New. (region_model::check_symbolic_bounds): Add "sval_hint" param. Pass it and sized_offset_reg to diagnostics. (region_model::check_region_bounds): Add "sval_hint" param, passing it to diagnostics. * diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic): Pass logger to pending_diagnostic::emit. * engine.cc: Add logger param to pending_diagnostic::emit implementations. * infinite-recursion.cc: Likewise. * kf-analyzer.cc: Likewise. * kf.cc: Likewise. Add nullptr for new param of check_region_for_write. * pending-diagnostic.h: Likewise in decl. * region-model-manager.cc (region_model_manager::get_or_create_int_cst): Convert param from poly_int64 to const poly_wide_int_ref &. (region_model_manager::maybe_fold_binop): Support type being NULL when checking for floating-point types. Check for (X + Y) - X => Y. Be less strict about types when folding associative ops. Check for (X + Y) * CST => (X * CST) + (Y * CST). * region-model-manager.h (region_model_manager::get_or_create_int_cst): Convert param from poly_int64 to const poly_wide_int_ref &. * region-model.cc: Add logger param to pending_diagnostic::emit implementations. (region_model::check_external_function_for_access_attr): Update for new param of check_region_for_write. (region_model::deref_rvalue): Use nullptr rather than NULL. (region_model::get_capacity): Handle RK_STRING. (region_model::check_region_access): Add "sval_hint" param; pass it to check_region_bounds. (region_model::check_region_for_write): Add "sval_hint" param; pass it to check_region_access. (region_model::check_region_for_read): Add NULL for new param to check_region_access. (region_model::set_value): Pass rhs_sval to check_region_for_write. (region_model::get_representative_path_var_1): Handle SK_CONSTANT in the check for infinite recursion. * region-model.h (region_model::check_region_for_write): Add "sval_hint" param. (region_model::check_region_access): Likewise. (region_model::check_symbolic_bounds): Likewise. (region_model::check_region_bounds): Likewise. * region.cc (region_offset::make_byte_offset): New. (region_offset::calc_symbolic_bit_offset): New. (region_offset::calc_symbolic_byte_offset): New. (region_offset::dump_to_pp): New. (region_offset::dump): New. (struct linear_op): New. (operator<, operator<=, operator>, operator>=): New, for region_offset. (region::get_next_offset): New. (region::get_relative_symbolic_offset): Use ptrdiff_type_node. (field_region::get_relative_symbolic_offset): Likewise. (element_region::get_relative_symbolic_offset): Likewise. (bit_range_region::get_relative_symbolic_offset): Likewise. * region.h (region::get_next_offset): New decl. * sm-fd.cc: Add logger param to pending_diagnostic::emit implementations. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-pattern-test.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * store.cc (bit_range::contains_p): Allow "out" to be null. * store.h (byte_range::get_start_bit_offset): New. (byte_range::get_next_bit_offset): New. * varargs.cc: Add logger param to pending_diagnostic::emit implementations. gcc/testsuite/ChangeLog: PR analyzer/106626 * gcc.dg/analyzer/data-model-1.c (test_16): Update for out-of-bounds working. * gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-json.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-10.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-11.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-12.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-13.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-14.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-15.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-2.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-3.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-4.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-6.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-7.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-8.c: New test. * gcc.dg/analyzer/out-of-bounds-diagram-9.c: New test. * gcc.dg/analyzer/pattern-test-2.c: Update expected results. * gcc.dg/analyzer/pr101962.c: Update expected results. * gcc.dg/plugin/analyzer_gil_plugin.c: Add logger param to pending_diagnostic::emit implementations. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-06-21diagnostics: add support for "text art" diagramsDavid Malcolm7-0/+500
Existing text output in GCC has to be implemented by writing sequentially to a pretty_printer instance. This makes it hard to implement some kinds of diagnostic output (see e.g. diagnostic-show-locus.cc). This patch adds more flexible ways of creating text output: - a canvas class, which can be "painted" to via random-access (rather that sequentially) - a table class for 2D grid layout, supporting items that span multiple rows/columns - a widget class for organizing diagrams hierarchically. The patch also expands GCC's diagnostics subsystem so that diagnostics can have "text art" diagrams - think ASCII art, but potentially including some Unicode characters, such as box-drawing chars. The new code is in a new "gcc/text-art" subdirectory and "text_art" namespace. The patch adds a new "-fdiagnostics-text-art-charset=VAL" option, with values: - "none": don't emit diagrams (added to -fdiagnostics-plain-output) - "ascii": use pure ASCII in diagrams - "unicode": allow for conservative use of unicode drawing characters (such as box-drawing characters). - "emoji" (the default): as "unicode", but potentially allow for conservative use of emoji in the output (such as U+26A0 WARNING SIGN). I made it possible to disable emoji separately from unicode as I believe there's a generation gap in acceptance of these characters (some older programmers have a visceral reaction against them, whereas younger programmers may have no problem with them). Diagrams are emitted to stderr by default. With SARIF output they are captured as a location in "relatedLocations", with the diagram as a code block in Markdown within a "markdown" property of a message. This patch doesn't add any such diagram usage to GCC, saving that for followups, apart from adding a plugin to the test suite to exercise the functionality. contrib/ChangeLog: * unicode/gen-box-drawing-chars.py: New file. * unicode/gen-combining-chars.py: New file. * unicode/gen-printable-chars.py: New file. gcc/ChangeLog: * Makefile.in (OBJS-libcommon): Add text-art/box-drawing.o, text-art/canvas.o, text-art/ruler.o, text-art/selftests.o, text-art/style.o, text-art/styled-string.o, text-art/table.o, text-art/theme.o, and text-art/widget.o. * color-macros.h (COLOR_FG_BRIGHT_BLACK): New. (COLOR_FG_BRIGHT_RED): New. (COLOR_FG_BRIGHT_GREEN): New. (COLOR_FG_BRIGHT_YELLOW): New. (COLOR_FG_BRIGHT_BLUE): New. (COLOR_FG_BRIGHT_MAGENTA): New. (COLOR_FG_BRIGHT_CYAN): New. (COLOR_FG_BRIGHT_WHITE): New. (COLOR_BG_BRIGHT_BLACK): New. (COLOR_BG_BRIGHT_RED): New. (COLOR_BG_BRIGHT_GREEN): New. (COLOR_BG_BRIGHT_YELLOW): New. (COLOR_BG_BRIGHT_BLUE): New. (COLOR_BG_BRIGHT_MAGENTA): New. (COLOR_BG_BRIGHT_CYAN): New. (COLOR_BG_BRIGHT_WHITE): New. * common.opt (fdiagnostics-text-art-charset=): New option. (diagnostic-text-art.h): New SourceInclude. (diagnostic_text_art_charset) New Enum and EnumValues. * configure: Regenerate. * configure.ac (gccdepdir): Add text-art to loop. * diagnostic-diagram.h: New file. * diagnostic-format-json.cc (json_emit_diagram): New. (diagnostic_output_format_init_json): Wire it up to context->m_diagrams.m_emission_cb. * diagnostic-format-sarif.cc: Include "diagnostic-diagram.h" and "text-art/canvas.h". (sarif_result::on_nested_diagnostic): Move code to... (sarif_result::add_related_location): ...this new function. (sarif_result::on_diagram): New. (sarif_builder::emit_diagram): New. (sarif_builder::make_message_object_for_diagram): New. (sarif_emit_diagram): New. (diagnostic_output_format_init_sarif): Set context->m_diagrams.m_emission_cb to sarif_emit_diagram. * diagnostic-text-art.h: New file. * diagnostic.cc: Include "diagnostic-text-art.h", "diagnostic-diagram.h", and "text-art/theme.h". (diagnostic_initialize): Initialize context->m_diagrams and call diagnostics_text_art_charset_init. (diagnostic_finish): Clean up context->m_diagrams.m_theme. (diagnostic_emit_diagram): New. (diagnostics_text_art_charset_init): New. * diagnostic.h (text_art::theme): New forward decl. (class diagnostic_diagram): Likewise. (diagnostic_context::m_diagrams): New field. (diagnostic_emit_diagram): New decl. * doc/invoke.texi (Diagnostic Message Formatting Options): Add -fdiagnostics-text-art-charset=. (-fdiagnostics-plain-output): Add -fdiagnostics-text-art-charset=none. * gcc.cc: Include "diagnostic-text-art.h". (driver_handle_option): Handle OPT_fdiagnostics_text_art_charset_. * opts-common.cc (decode_cmdline_options_to_array): Add "-fdiagnostics-text-art-charset=none" to expanded_args for -fdiagnostics-plain-output. * opts.cc: Include "diagnostic-text-art.h". (common_handle_option): Handle OPT_fdiagnostics_text_art_charset_. * pretty-print.cc (pp_unicode_character): New. * pretty-print.h (pp_unicode_character): New decl. * selftest-run-tests.cc: Include "text-art/selftests.h". (selftest::run_tests): Call text_art_tests. * text-art/box-drawing-chars.inc: New file, generated by contrib/unicode/gen-box-drawing-chars.py. * text-art/box-drawing.cc: New file. * text-art/box-drawing.h: New file. * text-art/canvas.cc: New file. * text-art/canvas.h: New file. * text-art/ruler.cc: New file. * text-art/ruler.h: New file. * text-art/selftests.cc: New file. * text-art/selftests.h: New file. * text-art/style.cc: New file. * text-art/styled-string.cc: New file. * text-art/table.cc: New file. * text-art/table.h: New file. * text-art/theme.cc: New file. * text-art/theme.h: New file. * text-art/types.h: New file. * text-art/widget.cc: New file. * text-art/widget.h: New file. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-text-art-ascii-bw.c: New test. * gcc.dg/plugin/diagnostic-test-text-art-ascii-color.c: New test. * gcc.dg/plugin/diagnostic-test-text-art-none.c: New test. * gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c: New test. * gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c: New test. * gcc.dg/plugin/diagnostic_plugin_test_text_art.c: New test plugin. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add them. libcpp/ChangeLog: * charset.cc (get_cppchar_property): New function template, based on... (cpp_wcwidth): ...this function. Rework to use the above. Include "combining-chars.inc". (cpp_is_combining_char): New function Include "printable-chars.inc". (cpp_is_printable_char): New function * combining-chars.inc: New file, generated by contrib/unicode/gen-combining-chars.py. * include/cpplib.h (cpp_is_combining_char): New function decl. (cpp_is_printable_char): New function decl. * printable-chars.inc: New file, generated by contrib/unicode/gen-printable-chars.py. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-03-24diagnostics: ensure that .sarif files are UTF-8 encoded [PR109098]David Malcolm3-0/+4
PR analyzer/109098 notes that the SARIF spec mandates that .sarif files are UTF-8 encoded, but -fdiagnostics-format=sarif-file naively assumes that the source files are UTF-8 encoded when quoting source artefacts in the .sarif output, which can lead to us writing out .sarif files with non-UTF-8 bytes in them (which break my reporting scripts). The root cause is that sarif_builder::maybe_make_artifact_content_object was using maybe_read_file to load the file content as bytes, and assuming they were UTF-8 encoded. This patch reworks both overloads of this function (one used for the whole file, the other for snippets of quoted lines) so that they go through input.cc's file cache, which attempts to decode the input files according to the input charset, and then encode as UTF-8. They also check that the result actually is UTF-8, for cases where the input charset is missing, or incorrectly specified, and omit the quoted source for such awkward cases. Doing so fixes all of the cases I've encountered. The patch adds a new: { dg-final { verify-sarif-file } } directive to all SARIF test cases in the test suite, which verifies that the output is UTF-8 encoded, and is valid JSON. In particular it verifies that when we complain about encoding problems, the .sarif report we emit is itself correctly encoded. gcc/ChangeLog: PR analyzer/109098 * diagnostic-format-sarif.cc (read_until_eof): Delete. (maybe_read_file): Delete. (sarif_builder::maybe_make_artifact_content_object): Use get_source_file_content rather than maybe_read_file. Reject it if it's not valid UTF-8. * input.cc (file_cache_slot::get_full_file_content): New. (get_source_file_content): New. (selftest::check_cpp_valid_utf8_p): New. (selftest::test_cpp_valid_utf8_p): New. (selftest::input_cc_tests): Call selftest::test_cpp_valid_utf8_p. * input.h (get_source_file_content): New prototype. gcc/testsuite/ChangeLog: PR analyzer/109098 * c-c++-common/diagnostic-format-sarif-file-1.c: Add verify-sarif-file directive. * c-c++-common/diagnostic-format-sarif-file-2.c: Likewise. * c-c++-common/diagnostic-format-sarif-file-3.c: Likewise. * c-c++-common/diagnostic-format-sarif-file-4.c: Likewise. * c-c++-common/diagnostic-format-sarif-file-Wbidi-chars.c: New test case, adapted from Wbidi-chars-1.c. * c-c++-common/diagnostic-format-sarif-file-bad-utf8-pr109098-1.c: New test case. * c-c++-common/diagnostic-format-sarif-file-bad-utf8-pr109098-2.c: New test case. * c-c++-common/diagnostic-format-sarif-file-bad-utf8-pr109098-3.c: New test case, adapted from cpp/Winvalid-utf8-1.c. * c-c++-common/diagnostic-format-sarif-file-valid-CP850.c: New test case, adapted from gcc.dg/diagnostic-input-charset-1.c. * gcc.dg/plugin/crash-test-ice-sarif.c: Add verify-sarif-file directive. * gcc.dg/plugin/crash-test-write-though-null-sarif.c: Likewise. * gcc.dg/plugin/diagnostic-test-paths-5.c: Likewise. * lib/scansarif.exp (verify-sarif-file): New procedure. * lib/verify-sarif-file.py: New support script. libcpp/ChangeLog: PR analyzer/109098 * charset.cc (cpp_valid_utf8_p): New function. * include/cpplib.h (cpp_valid_utf8_p): New prototype. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-03-18testsuite: Skip some gcc.dg/plugin tests for default_packed targetsHans-Peter Nilsson7-0/+7
Avoid unweildy structure-layout-specific message-matching expressions by exluding targets that lay out structures as if they had been specified with __attribute__ ((__packed__)), for tests where multiple messages depend on the structure layout. It's arguably a judgement call whether to skip some of these tests or add multiple lines of matches depending on the layout of structures. * gcc.dg/plugin/infoleak-2.c, gcc.dg/plugin/infoleak-CVE-2011-1078-1.c, gcc.dg/plugin/infoleak-CVE-2011-1078-2.c, gcc.dg/plugin/infoleak-CVE-2017-18549-1.c, gcc.dg/plugin/infoleak-CVE-2017-18550-1.c, gcc.dg/plugin/infoleak-antipatterns-1.c, gcc.dg/plugin/infoleak-fixit-1.c: Skip for default_packed targets.
2023-03-15diagnostics: attempt to capture crash info in SARIF output [PR109097]David Malcolm6-0/+282
As noted in PR analyzer/109097, if an internal compiler error occurs when -fdiagnostics-format=sarif-file is specified, we currently fail to write out a .sarif file, and the output to stderr doesn't contain "internal compiler error" or "Internal compiler error"; just the backtrace if we're lucky, and the "Please submit a full bug report" messages. This is a nuisance e.g. for my integration testing of -fanalyzer, where I'm gathering the results of builds via the .sarif output: if it crashes on a particular source file, then no output is generated, and it's effectively silent about the crash. This patch fixes things by adding a callback to diagnostic_context so that the SARIF output code can make one final attempt to write its output if an ICE occurs. It also special-cases the output, so that an ICE is treated as an "error"-level "notification" relating to the operation of the tool (SARIF v2.1.0 section 3.58), rather than a "result" about the code being analyzed by the tool. The patch adds test coverage for this via a plugin that can inject: * calls to internal_compiler_error, and * writes through a NULL pointer and verifying that a .sarif file is written out capturing the crash (and also that an ICE occurs via dg-ice, which seems to treat the ICE as an XFAIL, which is reasonable). I've added support for this to my integration-testing scripts: testing shows that with this patch we capture analyzer crashes in .sarif files (specifically, the analyzer crash on qemu: PR analyzer/109094), and I've updated my scripts to work with and report such output. I manually verified that the resulting .sarif files validate against the schema. gcc/ChangeLog: PR analyzer/109097 * diagnostic-format-sarif.cc (class sarif_invocation): New. (class sarif_ice_notification): New. (sarif_builder::m_invocation_obj): New field. (sarif_invocation::add_notification_for_ice): New. (sarif_invocation::prepare_to_flush): New. (sarif_ice_notification::sarif_ice_notification): New. (sarif_builder::sarif_builder): Add m_invocation_obj. (sarif_builder::end_diagnostic): Special-case DK_ICE and DK_ICE_NOBT. (sarif_builder::flush_to_file): Call prepare_to_flush on m_invocation_obj. Pass the latter to make_top_level_object. (sarif_builder::make_result_object): Move creation of "locations" array to... (sarif_builder::make_locations_arr): ...this new function. (sarif_builder::make_top_level_object): Add "invocation_obj" param and pass it to make_run_object. (sarif_builder::make_run_object): Add "invocation_obj" param and use it. (sarif_ice_handler): New callback. (diagnostic_output_format_init_sarif): Wire up sarif_ice_handler. * diagnostic.cc (diagnostic_initialize): Initialize new field "ice_handler_cb". (diagnostic_action_after_output): If it is set, make one attempt to call ice_handler_cb. * diagnostic.h (diagnostic_context::ice_handler_cb): New field. gcc/testsuite/ChangeLog: PR analyzer/109097 * c-c++-common/diagnostic-format-sarif-file-1.c: Verify that we have an invocation object marked as succeeding, with no notifications. * gcc.dg/plugin/crash-test-ice-sarif.c: New test. * gcc.dg/plugin/crash-test-ice-stderr.c: New test. * gcc.dg/plugin/crash-test-write-though-null-sarif.c: New test. * gcc.dg/plugin/crash-test-write-though-null-stderr.c: New test. * gcc.dg/plugin/crash_test_plugin.c: New plugin. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new plugin and test cases. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2023-03-07testsuite: Gate gcc.dg/plugin/must-tail-call-1.c and -2.c on tail_callHans-Peter Nilsson2-0/+2
While gcc.dg/plugin/must-tail-call-2.c passes for all targets even without this, the error message is, for a target like cris-elf that doesn't implement sibling calls: "error: cannot tail-call: machine description does not have a sibcall_epilogue instruction pattern" rather than "error: cannot tail-call: callee returns a structure". Also, it'd be confusing to exclude must-tail-call-1.c but not must-tail-call-2.c * gcc.dg/plugin/must-tail-call-1.c, gcc.dg/plugin/must-tail-call-2.c: Gate on effective target tail_call.
2023-02-28testsuite: No xfail infoleak-vfio_iommu_type1.c bogus for default_packedHans-Peter Nilsson1-3/+3
There are no messages about padding for targets that don't pad, i.e. default_packed. Noticed for cris-elf, verified for pru-elf at gcc-testresults@. testsuite: * gcc.dg/plugin/infoleak-vfio_iommu_type1.c: Don't xfail bogus message for "default_packed" targets.
2023-01-16Update copyright years.Jakub Jelinek1-1/+1
2022-12-06analyzer: split out more stuff from region-model-impl-calls.ccDavid Malcolm2-0/+2
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-16analyzer: use known_function to simplify region_model::on_call_{pre,post}David Malcolm2-0/+15
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-13analyzer: new warning: -Wanalyzer-tainted-assertion [PR106235]David Malcolm1-1/+2
This patch adds a new -Wanalyzer-tainted-assertion warning to -fanalyzer's "taint" mode (which also requires -fanalyzer-checker=taint). It complains about attacker-controlled values being used in assertions, or in any expression affecting control flow that guards a "noreturn" function. As noted in the docs part of the patch, in such cases: - when assertion-checking is enabled: an attacker could trigger a denial of service by injecting an assertion failure - when assertion-checking is disabled, such as by defining NDEBUG, an attacker could inject data that subverts the process, since it presumably violates a precondition that is being assumed by the code. For example, given: #include <assert.h> int __attribute__((tainted_args)) test_tainted_assert (int n) { assert (n > 0); return n * n; } compiling with -fanalyzer -fanalyzer-checker=taint gives: t.c: In function 'test_tainted_assert': t.c:6:3: warning: use of attacked-controlled value in condition for assertion [CWE-617] [-Wanalyzer-tainted-assertion] 6 | assert (n > 0); | ^~~~~~ 'test_tainted_assert': event 1 | | 4 | test_tainted_assert (int n) | | ^~~~~~~~~~~~~~~~~~~ | | | | | (1) function 'test_tainted_assert' marked with '__attribute__((tainted_args))' | +--> 'test_tainted_assert': event 2 | | 4 | test_tainted_assert (int n) | | ^~~~~~~~~~~~~~~~~~~ | | | | | (2) entry to 'test_tainted_assert' | 'test_tainted_assert': events 3-6 | |/usr/include/assert.h:106:10: | 106 | if (expr) \ | | ^ | | | | | (3) use of attacker-controlled value for control flow | | (4) following 'false' branch (when 'n <= 0')... |...... | 109 | __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \ | | ~~~~~~~~~~~~~ | | | | | (5) ...to here | | (6) treating '__assert_fail' as an assertion failure handler due to '__attribute__((__noreturn__))' | The testcases have various examples for BUG and BUG_ON from the Linux kernel; there, the diagnostic treats "panic" as an assertion failure handler, due to '__attribute__((__noreturn__))'. gcc/analyzer/ChangeLog: PR analyzer/106235 * analyzer.opt (Wanalyzer-tainted-assertion): New. * checker-path.cc (checker_path::fixup_locations): Pass false to pending_diagnostic::fixup_location. * diagnostic-manager.cc (get_emission_location): Pass true to pending_diagnostic::fixup_location. * pending-diagnostic.cc (pending_diagnostic::fixup_location): Add bool param. * pending-diagnostic.h (pending_diagnostic::fixup_location): Add bool param to decl. * sm-taint.cc (taint_state_machine::m_tainted_control_flow): New. (taint_diagnostic::describe_state_change): Drop "final". (class tainted_assertion): New. (taint_state_machine::taint_state_machine): Initialize m_tainted_control_flow. (taint_state_machine::alt_get_inherited_state): Support comparisons being tainted, based on their arguments. (is_assertion_failure_handler_p): New. (taint_state_machine::on_stmt): Complain about calls to assertion failure handlers guarded by an attacker-controller conditional. Detect attacker-controlled gcond conditionals and gswitch index values. (taint_state_machine::check_control_flow_arg_for_taint): New. gcc/ChangeLog: PR analyzer/106235 * doc/gcc/gcc-command-options/option-summary.rst: Add -Wno-analyzer-tainted-assertion. * doc/gcc/gcc-command-options/options-that-control-static-analysis.rst: Add -Wno-analyzer-tainted-assertion. gcc/testsuite/ChangeLog: PR analyzer/106235 * gcc.dg/analyzer/taint-assert-BUG_ON.c: New test. * gcc.dg/analyzer/taint-assert-macro-expansion.c: New test. * gcc.dg/analyzer/taint-assert.c: New test. * gcc.dg/analyzer/taint-assert-system-header.c: New test. * gcc.dg/analyzer/test-assert.h: New header. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::fixup_location): Add bool param. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-03analyzer: use std::unique_ptr for state machines from pluginsDavid Malcolm1-1/+2
gcc/analyzer/ChangeLog: * analyzer.h: Use std::unique_ptr for state machines from plugins. * engine.cc: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: Use std::unique_ptr for state machines from plugins. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-03analyzer: use std::unique_ptr for known functionsDavid Malcolm2-6/+8
gcc/analyzer/ChangeLog: * analyzer.h: Use std::unique_ptr for known functions. * engine.cc: Likewise. * known-function-manager.cc: Likewise. * known-function-manager.h: Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: Use std::unique_ptr for known functions. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-03analyzer: use std::unique_ptr during bifurcationDavid Malcolm2-2/+4
gcc/analyzer/ChangeLog: * analysis-plan.cc: Define INCLUDE_MEMORY before including system.h. * analyzer-pass.cc: Likewise. * analyzer-selftests.cc: Likewise. * analyzer.cc: Likewise. * analyzer.h: Use std::unique_ptr in bifurcation code. * call-string.cc: Define INCLUDE_MEMORY before including system.h. * complexity.cc: Likewise. * engine.cc: Use std::unique_ptr in bifurcation code. * exploded-graph.h: Likewise. * known-function-manager.cc: Define INCLUDE_MEMORY before including system.h. * region-model-impl-calls.cc: Use std::unique_ptr in bifurcation code. * region-model.cc: Likewise. * region-model.h: Likewise. * supergraph.cc: Define INCLUDE_MEMORY before including system.h. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: Include "make-unique.h". Use std::unique_ptr in bifurcation code. * gcc.dg/plugin/analyzer_known_fns_plugin.c: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-11-03analyzer: use std::unique_ptr for pending_diagnostic/noteDavid Malcolm3-5/+9
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-09-09analyzer: implement trust boundaries via a plugin for Linux kernelDavid Malcolm28-0/+2574
This is a less ambitious version of: [PATCH 0/6] RFC: adding support to GCC for detecting trust boundaries https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584372.html Earlier versions of this patch attempted: (a) various ways of identifying "untrusted" memory regions (b) providing a way to support the Linux kernel's "__user" annotation, either via type attributes, or via custom address spaces (c) enough attributes to identify "copy_from_user" and "copy_to_user", (d) wiring all of the above together to detect infoleaks and taint This patch adds a new -Wanalyzer-exposure-through-uninit-copy, emitted by -fanalyzer if it detects copying of uninitialized data through a pointer to an untrusted region, but requires a plugin to tell it when a copy crosses a trust boundary. This patch adds a proof-of-concept gcc plugin for the analyzer for use with the Linux kernel that special-cases calls to "copy_from_user" and calls to "copy_to_user": calls to copy_to_user are checked for -Wanalyzer-exposure-through-uninit-copy, and data copied via copy_from_user is marked as tainted when -fanalyzer-checker=taint is active. This is very much just a proof-of-concept. A big limitation is that the copy_{from,to}_user special-casing only happens if these functions have no body in the TU being analyzed, which isn't the case for a normal kernel build. I'd much prefer to provide a more general mechanism for handling such behavior without resorting to plugins (e.g. via attributes or custom address spaces), but in the interest of not "letting perfect be the enemy of the good" this patch at least allows parts of this "trust boundaries" code to be merged for experimentation with the idea. The -Wanalyzer-exposure-through-uninit-copy diagnostic uses notes to express what fields and padding within a struct have not been initialized. For example: infoleak-CVE-2011-1078-2.c: In function 'test_1': infoleak-CVE-2011-1078-2.c:32:9: warning: potential exposure of sensitive information by copying uninitialized data from stack across trust boundary [CWE-200] [-Wanalyzer-exposure-through-uninit-copy] 32 | copy_to_user(optval, &cinfo, sizeof(cinfo)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'test_1': events 1-3 | | 25 | struct sco_conninfo cinfo; | | ^~~~~ | | | | | (1) region created on stack here | | (2) capacity: 6 bytes |...... | 32 | copy_to_user(optval, &cinfo, sizeof(cinfo)); | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (3) uninitialized data copied from stack here | infoleak-CVE-2011-1078-2.c:32:9: note: 1 byte is uninitialized 32 | copy_to_user(optval, &cinfo, sizeof(cinfo)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ infoleak-CVE-2011-1078-2.c:18:15: note: padding after field 'dev_class' is uninitialized (1 byte) 18 | __u8 dev_class[3]; | ^~~~~~~~~ infoleak-CVE-2011-1078-2.c:25:29: note: suggest forcing zero-initialization by providing a '{0}' initializer 25 | struct sco_conninfo cinfo; | ^~~~~ | = {0} For taint-detection, the patch includes a series of reproducers for detecting CVE-2011-0521. Unfortunately the analyzer doesn't yet detect the issue until the code has been significantly simplified from its original form: currently only in -5.c and -6.c in the series of test (see notes in the individual cases), such as: taint-CVE-2011-0521-6.c:33:48: warning: use of attacker-controlled value '*info.num' in array lookup without bounds checking [CWE-129] [-Wanalyzer-tainted-array-index] 33 | av7110->ci_slot[info->num].num = info->num; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~ 'test_1': events 1-3 | | 19 | if (copy_from_user(&sbuf, (void __user *)arg, sizeof(sbuf)) != 0) | | ^ | | | | | (1) following 'false' branch... |...... | 23 | struct dvb_device *dvbdev = file->private_data; | | ~~~~~~ | | | | | (2) ...to here |...... | 33 | av7110->ci_slot[info->num].num = info->num; | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (3) use of attacker-controlled value '*info.num' in array lookup without bounds checking | The patch also includes various infoleak and taint cases from my antipatterns.ko kernel module: https://github.com/davidmalcolm/antipatterns.ko gcc/analyzer/ChangeLog: * analyzer.opt (Wanalyzer-exposure-through-uninit-copy): New. * checker-path.cc (region_creation_event::region_creation_event): Add "capacity" and "kind" params. (region_creation_event::get_desc): Generalize to different kinds of event. (checker_path::add_region_creation_event): Convert to... (checker_path::add_region_creation_events): ...this. * checker-path.h (enum rce_kind): New. (region_creation_event::region_creation_event): Add "capacity" and "kind" params. (region_creation_event::m_capacity): New field. (region_creation_event::m_rce_kind): New field. (checker_path::add_region_creation_event): Convert to... (checker_path::add_region_creation_events): ...this. * diagnostic-manager.cc (diagnostic_manager::build_emission_path): Update for multiple region creation events. (diagnostic_manager::add_event_on_final_node): Likewise. (diagnostic_manager::add_events_for_eedge): Likewise. * region-model-impl-calls.cc (call_details::get_logger): New. * region-model.cc: Define INCLUDE_MEMORY before including "system.h". Include "gcc-rich-location.h". (class record_layout): New. (class exposure_through_uninit_copy): New. (contains_uninit_p): New. (region_model::maybe_complain_about_infoleak): New. * region-model.h (call_details::get_logger): New decl. (region_model::maybe_complain_about_infoleak): New decl. (region_model::mark_as_tainted): New decl. * sm-taint.cc (region_model::mark_as_tainted): New. gcc/ChangeLog: * doc/invoke.texi (Static Analyzer Options): Add -Wanalyzer-exposure-through-uninit-copy. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_kernel_plugin.c: New test. * gcc.dg/plugin/copy_from_user-1.c: New test. * gcc.dg/plugin/infoleak-1.c: New test. * gcc.dg/plugin/infoleak-2.c: New test. * gcc.dg/plugin/infoleak-3.c: New test. * gcc.dg/plugin/infoleak-CVE-2011-1078-1.c: New test. * gcc.dg/plugin/infoleak-CVE-2011-1078-2.c: New test. * gcc.dg/plugin/infoleak-CVE-2014-1446-1.c: New test. * gcc.dg/plugin/infoleak-CVE-2017-18549-1.c: New test. * gcc.dg/plugin/infoleak-CVE-2017-18550-1.c: New test. * gcc.dg/plugin/infoleak-antipatterns-1.c: New test. * gcc.dg/plugin/infoleak-fixit-1.c: New test. * gcc.dg/plugin/infoleak-net-ethtool-ioctl.c: New test. * gcc.dg/plugin/infoleak-vfio_iommu_type1.c: New test. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add analyzer_kernel_plugin.c and the new test cases. * gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-1.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-2.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-3.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-4.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-5.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521-6.c: New test. * gcc.dg/plugin/taint-CVE-2011-0521.h: New test. * gcc.dg/plugin/taint-antipatterns-1.c: New test. * gcc.dg/plugin/test-uaccess.h: New header for tests. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-09-09analyzer: add support for plugin-supplied known function behaviorsDavid Malcolm3-0/+264
This patch adds the ability for plugins to register "known functions" with the analyzer, identified by name. If -fanalyzer sees a call to such a function (with no body), it will use a plugin-provided subclass of the new known_function abstract base class to model the possible outcomes of the function call. gcc/ChangeLog: * Makefile.in (ANALYZER_OBJS): Add analyzer/known-function-manager.o. gcc/analyzer/ChangeLog: * analyzer.h (class known_function_manager): New forward decl. (class known_function): New. (plugin_analyzer_init_iface::register_known_function): New. * engine.cc: Include "analyzer/known-function-manager.h". (plugin_analyzer_init_impl::plugin_analyzer_init_impl): Add known_fn_mgr param. (plugin_analyzer_init_impl::register_state_machine): Add LOC_SCOPE. (plugin_analyzer_init_impl::register_known_function): New. (plugin_analyzer_init_impl::m_known_fn_mgr): New. (impl_run_checkers): Update plugin callback invocation to use eng's known_function_manager. * known-function-manager.cc: New file. * known-function-manager.h: New file. * region-model-manager.cc (region_model_manager::region_model_manager): Pass logger to m_known_fn_mgr's ctor. * region-model.cc (region_model::update_for_zero_return): New. (region_model::update_for_nonzero_return): New. (maybe_simplify_upper_bound): New. (region_model::maybe_get_copy_bounds): New. (region_model::get_known_function): New. (region_model::on_call_pre): Handle plugin-supplied known functions. * region-model.h: Include "analyzer/known-function-manager.h". (region_model_manager::get_known_function_manager): New. (region_model_manager::m_known_fn_mgr): New. (call_details::get_model): New accessor. (region_model::maybe_get_copy_bounds): New decl. (region_model::update_for_zero_return): New decl. (region_model::update_for_nonzero_return): New decl. (region_model::get_known_function): New decl. (region_model::get_known_function_manager): New. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_known_fns_plugin.c: New test plugin. * gcc.dg/plugin/known-fns-1.c: New test. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new plugin and test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-06-23diagnostics: add ability to associate diagnostics with rules from coding ↵David Malcolm2-2/+9
standards gcc/ChangeLog: * common.opt (fdiagnostics-show-rules): New option. * diagnostic-format-json.cc (diagnostic_output_format_init_json): Fix up context->show_rules. * diagnostic-format-sarif.cc (diagnostic_output_format_init_sarif): Likewise. * diagnostic-metadata.h (diagnostic_metadata::rule): New class. (diagnostic_metadata::precanned_rule): New class. (diagnostic_metadata::add_rule): New. (diagnostic_metadata::get_num_rules): New. (diagnostic_metadata::get_rule): New. (diagnostic_metadata::m_rules): New field. * diagnostic.cc (diagnostic_initialize): Initialize show_rules. (print_any_rules): New. (diagnostic_report_diagnostic): Call it. * diagnostic.h (diagnostic_context::show_rules): New field. * doc/invoke.texi (-fno-diagnostics-show-rules): New option. * opts.cc (common_handle_option): Handle OPT_fdiagnostics_show_rules. * toplev.cc (general_init): Set up global_dc->show_rules. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-metadata.c: Expect " [STR34-C]" to be emitted at the "gets" call. * gcc.dg/plugin/diagnostic_plugin_test_metadata.c (pass_test_metadata::execute): Associate the "gets" diagnostic with a rule named "STR34-C". Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-06-02diagnostics: add SARIF output formatDavid Malcolm3-0/+72
This patch adds support to gcc's diagnostic subsystem for emitting diagnostics in SARIF, aka the Static Analysis Results Interchange Format: https://sarifweb.azurewebsites.net/ by extending -fdiagnostics-format= to add two new options: -fdiagnostics-format=sarif-stderr and: -fdiagnostics-format=sarif-file The patch targets SARIF v2.1.0 This is a JSON-based format suited for capturing the results of static analysis tools (like GCC's -fanalyzer), but it can also be used for plain GCC warnings and errors. SARIF supports per-event metadata in diagnostic paths such as ["acquire", "resource"] and ["release", "lock"] (specifically, the threadFlowLocation "kinds" property: SARIF v2.1.0 section 3.38.8), so the patch extends GCC"s diagnostic_event subclass with a "struct meaning" with similar purpose. The patch implements this for -fanalyzer so that the various state-machine-based warnings set these in the SARIF output. The heart of the implementation is in the new file diagnostic-format-sarif.cc. Much of the rest of the patch is interface classes, isolating the diagnostic subsystem (which has no knowledge of e.g. tree or langhook) from the "client" code in the compiler proper cc1 etc). The patch adds a langhook for specifying the SARIF v2.1.0 "artifact.sourceLanguage" property, based on the list in SARIF v2.1.0 Appendix J. The patch adds automated DejaGnu tests to our testsuite via new scan-sarif-file and scan-sarif-file-not directives (although these merely use regexps, rather than attempting to use a proper JSON parser). I've tested the patch by hand using the validator at: https://sarifweb.azurewebsites.net/Validation and the react-based viewer at: https://microsoft.github.io/sarif-web-component/ which successfully shows most of the information (although not paths, and not CWE IDs), and I've fixed all validation errors I've seen (though bugs no doubt remain). I've also tested the generated SARIF using the VS Code extension linked to from the SARIF website; I'm a novice with VS Code, but it seems to be able to handle my generated SARIF files (e.g. showing the data in the SARIF tab, and showing squiggly underlines under issues, and when I click on them, it visualizes the events in the path inline within the source window). Has anyone written an Emacs mode for SARIF files? (pretty please) gcc/ChangeLog: * Makefile.in (OBJS): Add tree-diagnostic-client-data-hooks.o and tree-logical-location.o. (OBJS-libcommon): Add diagnostic-format-sarif.o; reorder. (CFLAGS-tree-diagnostic-client-data-hooks.o): Add TARGET_NAME. * common.opt (fdiagnostics-format=): Add sarif-stderr and sarif-file. (sarif-stderr, sarif-file): New enum values. * diagnostic-client-data-hooks.h: New file. * diagnostic-format-sarif.cc: New file. * diagnostic-path.h (enum diagnostic_event::verb): New enum. (enum diagnostic_event::noun): New enum. (enum diagnostic_event::property): New enum. (struct diagnostic_event::meaning): New struct. (diagnostic_event::get_logical_location): New vfunc. (diagnostic_event::get_meaning): New vfunc. (simple_diagnostic_event::get_logical_location): New vfunc impl. (simple_diagnostic_event::get_meaning): New vfunc impl. * diagnostic.cc: Include "diagnostic-client-data-hooks.h". (diagnostic_initialize): Initialize m_client_data_hooks. (diagnostic_finish): Clean up m_client_data_hooks. (diagnostic_event::meaning::dump_to_pp): New. (diagnostic_event::meaning::maybe_get_verb_str): New. (diagnostic_event::meaning::maybe_get_noun_str): New. (diagnostic_event::meaning::maybe_get_property_str): New. (get_cwe_url): Make non-static. (diagnostic_output_format_init): Handle DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR and DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE. * diagnostic.h (enum diagnostics_output_format): Add DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR and DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE. (class diagnostic_client_data_hooks): New forward decl. (class logical_location): New forward decl. (diagnostic_context::m_client_data_hooks): New field. (diagnostic_output_format_init_sarif_stderr): New decl. (diagnostic_output_format_init_sarif_file): New decl. (get_cwe_url): New decl. * doc/invoke.texi (-fdiagnostics-format=): Add sarif-stderr and sarif-file. * doc/sourcebuild.texi (Scan a particular file): Add scan-sarif-file and scan-sarif-file-not. * langhooks-def.h (lhd_get_sarif_source_language): New decl. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): New macro. (LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE. * langhooks.cc (lhd_get_sarif_source_language): New. * langhooks.h (lang_hooks::get_sarif_source_language): New field. * logical-location.h: New file. * plugin.cc (struct for_each_plugin_closure): New. (for_each_plugin_cb): New. (for_each_plugin): New. * plugin.h (for_each_plugin): New decl. * tree-diagnostic-client-data-hooks.cc: New file. * tree-diagnostic.cc: Include "diagnostic-client-data-hooks.h". (tree_diagnostics_defaults): Populate m_client_data_hooks. * tree-logical-location.cc: New file. * tree-logical-location.h: New file. gcc/ada/ChangeLog: * gcc-interface/misc.cc (gnat_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/analyzer/ChangeLog: * checker-path.cc (checker_event::get_meaning): New. (function_entry_event::get_meaning): New. (state_change_event::get_desc): Add dump of meaning of the event to the -fanalyzer-verbose-state-changes output. (state_change_event::get_meaning): New. (cfg_edge_event::get_meaning): New. (call_event::get_meaning): New. (return_event::get_meaning): New. (start_consolidated_cfg_edges_event::get_meaning): New. (warning_event::get_meaning): New. * checker-path.h: Include "tree-logical-location.h". (checker_event::checker_event): Construct m_logical_loc. (checker_event::get_logical_location): New. (checker_event::get_meaning): New decl. (checker_event::m_logical_loc): New. (function_entry_event::get_meaning): New decl. (state_change_event::get_meaning): New decl. (cfg_edge_event::get_meaning): New decl. (call_event::get_meaning): New decl. (return_event::get_meaning): New decl. (start_consolidated_cfg_edges_event::get_meaning): New. (warning_event::get_meaning): New decl. * pending-diagnostic.h: Include "diagnostic-path.h". (pending_diagnostic::get_meaning_for_state_change): New vfunc. * sm-file.cc (file_diagnostic::get_meaning_for_state_change): New vfunc impl. * sm-malloc.cc (malloc_diagnostic::get_meaning_for_state_change): Likewise. * sm-sensitive.cc (exposure_through_output_file::get_meaning_for_state_change): Likewise. * sm-taint.cc (taint_diagnostic::get_meaning_for_state_change): Likewise. * varargs.cc (va_list_sm_diagnostic::get_meaning_for_state_change): Likewise. gcc/c/ChangeLog: * c-lang.cc (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. (c_get_sarif_source_language): New. * c-tree.h (c_get_sarif_source_language): New decl. gcc/cp/ChangeLog: * cp-lang.cc (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. (cp_get_sarif_source_language): New. gcc/d/ChangeLog: * d-lang.cc (d_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/fortran/ChangeLog: * f95-lang.cc (gfc_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/go/ChangeLog: * go-lang.cc (go_get_sarif_source_language): New. (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. gcc/objc/ChangeLog: * objc-act.h (objc_get_sarif_source_language): New decl. * objc-lang.cc (LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE): Redefine. (objc_get_sarif_source_language): New. gcc/testsuite/ChangeLog: * c-c++-common/diagnostic-format-sarif-file-1.c: New test. * c-c++-common/diagnostic-format-sarif-file-2.c: New test. * c-c++-common/diagnostic-format-sarif-file-3.c: New test. * c-c++-common/diagnostic-format-sarif-file-4.c: New test. * gcc.dg/analyzer/file-meaning-1.c: New test. * gcc.dg/analyzer/malloc-meaning-1.c: New test. * gcc.dg/analyzer/malloc-sarif-1.c: New test. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::get_meaning_for_state_change): New vfunc impl. * gcc.dg/plugin/diagnostic-test-paths-5.c: New test. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add diagnostic-test-paths-5.c to tests for diagnostic_plugin_test_paths.c. * lib/gcc-dg.exp: Load scansarif.exp. * lib/scansarif.exp: New test. libatomic/ChangeLog: * testsuite/lib/libatomic.exp: Add load_gcc_lib of scansarif.exp. libgomp/ChangeLog: * testsuite/lib/libgomp.exp: Add load_gcc_lib of scansarif.exp. libitm/ChangeLog: * testsuite/lib/libitm.exp: Add load_gcc_lib of scansarif.exp. libphobos/ChangeLog: * testsuite/lib/libphobos-dg.exp: Add load_gcc_lib of scansarif.exp. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-05-23test plugins: use "final" and "override" directly, rather than via macrosDavid Malcolm1-18/+18
gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: Replace uses of "FINAL" and "OVERRIDE" with "final" and "override". Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-05-13Make gimple_build main workers more flexibleRichard Biener14-23/+18
The following makes the main gimple_build API take a gimple_stmt_iterator, whether to insert before or after and an iterator update argument to make it more convenient to use in certain situations (see the tree-vect-generic.cc hunks for an example). It also makes the case we insert into the IL somewhat distinct from inserting into a standalone sequence in that it simplifies built expressions the same way as inserting and calling fold_stmt (..., follow_all_ssa_edges) would. When inserting into a standalone sequence we restrict simplification to defs within the currently building sequence. The patch only amends the tree_code gimple_build API, I will followup with converting the rest as well. The patch got larger than intended because the template forwarders now use gsi_last which introduces a dependency on gimple-iterator.h requiring mass #include re-org across the tree. There are two frontend specific files including gimple-fold.h just for some padding clearing stuff - I've removed the include and instead moved the declarations to fold-const.h (but not the implementations). Otherwise I'd have to include half of the middle-end headers in those files which I didn't much like. 2022-05-12 Richard Biener <rguenther@suse.de> gcc/cp/ * constexpr.cc: Remove gimple-fold.h include. gcc/c-family/ * c-omp.cc: Remove gimple-fold.h include. gcc/analyzer/ * supergraph.cc: Re-order gimple-fold.h include. gcc/ * gimple-fold.cc (gimple_build): Adjust for new main API. * gimple-fold.h (gimple_build): New main APIs with iterator, insert direction and iterator update. (gimple_build): New forwarder template. (clear_padding_type_may_have_padding_p): Remove. (clear_type_padding_in_mask): Likewise. (arith_overflowed_p): Likewise. * fold-const.h (clear_padding_type_may_have_padding_p): Declare. (clear_type_padding_in_mask): Likewise. (arith_overflowed_p): Likewise. * tree-vect-generic.cc (gimplify_build3): Use main gimple_build API. (gimplify_build2): Likewise. (gimplify_build1): Likewise. * ubsan.cc (ubsan_expand_ptr_ifn): Likewise, avoid extra compare stmt. * gengtype.cc (open_base_files): Re-order includes. * builtins.cc: Re-order gimple-fold.h include. * calls.cc: Likewise. * cgraphbuild.cc: Likewise. * cgraphunit.cc: Likewise. * config/rs6000/rs6000-builtin.cc: Likewise. * config/rs6000/rs6000-call.cc: Likewise. * config/rs6000/rs6000.cc: Likewise. * config/s390/s390.cc: Likewise. * expr.cc: Likewise. * fold-const.cc: Likewise. * function-tests.cc: Likewise. * gimple-match-head.cc: Likewise. * gimple-range-fold.cc: Likewise. * gimple-ssa-evrp-analyze.cc: Likewise. * gimple-ssa-evrp.cc: Likewise. * gimple-ssa-sprintf.cc: Likewise. * gimple-ssa-warn-access.cc: Likewise. * gimplify.cc: Likewise. * graphite-isl-ast-to-gimple.cc: Likewise. * ipa-cp.cc: Likewise. * ipa-devirt.cc: Likewise. * ipa-prop.cc: Likewise. * omp-low.cc: Likewise. * pointer-query.cc: Likewise. * range-op.cc: Likewise. * tree-cfg.cc: Likewise. * tree-if-conv.cc: Likewise. * tree-inline.cc: Likewise. * tree-object-size.cc: Likewise. * tree-ssa-ccp.cc: Likewise. * tree-ssa-dom.cc: Likewise. * tree-ssa-forwprop.cc: Likewise. * tree-ssa-ifcombine.cc: Likewise. * tree-ssa-loop-ivcanon.cc: Likewise. * tree-ssa-math-opts.cc: Likewise. * tree-ssa-pre.cc: Likewise. * tree-ssa-propagate.cc: Likewise. * tree-ssa-reassoc.cc: Likewise. * tree-ssa-sccvn.cc: Likewise. * tree-ssa-strlen.cc: Likewise. * tree-ssa.cc: Likewise. * value-pointer-equiv.cc: Likewise. * vr-values.cc: Likewise. gcc/testsuite/ * gcc.dg/plugin/diagnostic_group_plugin.c: Reorder or remove gimple-fold.h include. * gcc.dg/plugin/diagnostic_plugin_show_trees.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_inlining.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_metadata.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_paths.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_string_literals.c: Likewise. * gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c: Likewise. * gcc.dg/plugin/finish_unit_plugin.c: Likewise. * gcc.dg/plugin/ggcplug.c: Likewise. * gcc.dg/plugin/must_tail_call_plugin.c: Likewise. * gcc.dg/plugin/one_time_plugin.c: Likewise. * gcc.dg/plugin/selfassign.c: Likewise. * gcc.dg/plugin/start_unit_plugin.c: Likewise. * g++.dg/plugin/selfassign.c: Likewise.
2022-03-16analyzer: early rejection of disabled warnings [PR104955]David Malcolm1-6/+10
Avoid generating execution paths for warnings that are ultimately rejected due to -Wno-analyzer-* flags. This improves the test case from taking at least several minutes (before I killed it) to taking under a second. This doesn't fix the slowdown seen in PR analyzer/104955 with large numbers of warnings when the warnings are still enabled. gcc/analyzer/ChangeLog: PR analyzer/104955 * diagnostic-manager.cc (get_emission_location): New. (diagnostic_manager::diagnostic_manager): Initialize m_num_disabled_diagnostics. (diagnostic_manager::add_diagnostic): Reject diagnostics that will eventually be rejected due to being disabled. (diagnostic_manager::emit_saved_diagnostics): Log the number of disabled diagnostics. (diagnostic_manager::emit_saved_diagnostic): Split out logic for determining emission location to get_emission_location. * diagnostic-manager.h (diagnostic_manager::m_num_disabled_diagnostics): New field. * engine.cc (stale_jmp_buf::get_controlling_option): New. (stale_jmp_buf::emit): Use it. * pending-diagnostic.h (pending_diagnostic::get_controlling_option): New vfunc. * region-model.cc (poisoned_value_diagnostic::get_controlling_option): New. (poisoned_value_diagnostic::emit): Use it. (shift_count_negative_diagnostic::get_controlling_option): New. (shift_count_negative_diagnostic::emit): Use it. (shift_count_overflow_diagnostic::get_controlling_option): New. (shift_count_overflow_diagnostic::emit): Use it. (dump_path_diagnostic::get_controlling_option): New. (dump_path_diagnostic::emit): Use it. (write_to_const_diagnostic::get_controlling_option): New. (write_to_const_diagnostic::emit): Use it. (write_to_string_literal_diagnostic::get_controlling_option): New. (write_to_string_literal_diagnostic::emit): Use it. * sm-file.cc (double_fclose::get_controlling_option): New. (double_fclose::emit): Use it. (file_leak::get_controlling_option): New. (file_leak::emit): Use it. * sm-malloc.cc (mismatching_deallocation::get_controlling_option): New. (mismatching_deallocation::emit): Use it. (double_free::get_controlling_option): New. (double_free::emit): Use it. (possible_null_deref::get_controlling_option): New. (possible_null_deref::emit): Use it. (possible_null_arg::get_controlling_option): New. (possible_null_arg::emit): Use it. (null_deref::get_controlling_option): New. (null_deref::emit): Use it. (null_arg::get_controlling_option): New. (null_arg::emit): Use it. (use_after_free::get_controlling_option): New. (use_after_free::emit): Use it. (malloc_leak::get_controlling_option): New. (malloc_leak::emit): Use it. (free_of_non_heap::get_controlling_option): New. (free_of_non_heap::emit): Use it. * sm-pattern-test.cc (pattern_match::get_controlling_option): New. (pattern_match::emit): Use it. * sm-sensitive.cc (exposure_through_output_file::get_controlling_option): New. (exposure_through_output_file::emit): Use it. * sm-signal.cc (signal_unsafe_call::get_controlling_option): New. (signal_unsafe_call::emit): Use it. * sm-taint.cc (tainted_array_index::get_controlling_option): New. (tainted_array_index::emit): Use it. (tainted_offset::get_controlling_option): New. (tainted_offset::emit): Use it. (tainted_size::get_controlling_option): New. (tainted_size::emit): Use it. (tainted_divisor::get_controlling_option): New. (tainted_divisor::emit): Use it. (tainted_allocation_size::get_controlling_option): New. (tainted_allocation_size::emit): Use it. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/many-disabled-diagnostics.c: New test. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::get_controlling_option): New. (double_save_thread::emit): Use it. (fncall_without_gil::emit): Likewise. (pyobject_usage_without_gil::emit): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2022-01-03Update copyright years.Jakub Jelinek1-1/+1
2021-10-20Trivial fix to gil-1.c when analyzer is not enabledJeff Law1-0/+1
gcc/testsuite * gcc.dg/plugin/gil-1.c: Add dg-require-effective-target marker.
2021-09-20Don't record string concatenation data for 'RESERVED_LOCATION_P'Thomas Schwinge1-2/+2
'RESERVED_LOCATION_P' means 'UNKNOWN_LOCATION' or 'BUILTINS_LOCATION'. We're using 'UNKNOWN_LOCATION' as a spare value for 'Empty', so should ascertain that we don't use it as a key additionally. Similarly for 'BUILTINS_LOCATION' that we'd later like to use as a spare value for 'Deleted'. As discussed in the source code comment added, for these we didn't have stable behavior anyway. Follow-up to r239175 (commit 88fa5555a309e5d6c6171b957daaf2f800920869) "On-demand locations within string-literals". gcc/ * input.c (string_concat_db::record_string_concatenation) (string_concat_db::get_string_concatenation): Skip for 'RESERVED_LOCATION_P'. gcc/testsuite/ * gcc.dg/plugin/diagnostic-test-string-literals-1.c: Adjust expected error diagnostics.
2021-07-07analyzer: remove add_any_constraints_from_ssa_def_stmtDavid Malcolm1-21/+0
I'm working on reimplementing -Wanalyzer-use-of-uninitialized-value, but I ran into issues with region_model::add_any_constraints_from_ssa_def_stmt. This function is from the initial commit of the analyzer and walks the SSA names finding conditions that were missed due to the GCC 10 era region_model not retaining useful information on how values were created; as of GCC 11 the symbolic values contain this information, and so the conditions can be reconstructed from them instead. region_model::add_any_constraints_from_ssa_def_stmt is a liability when tracking uninitialized values as it requires looking up SSA values when those values may have been purged, thus greatly complicating detection of uses of uninitialized values. It's simplest to eliminate it and reimplement the condition-finding via the makeup of the svalues, which this patch does. Doing so requires supporting add_condition on svalues rather than just on trees, which requires some changes to ana::state_machine and its subclasses. gcc/analyzer/ChangeLog: * diagnostic-manager.cc (null_assignment_sm_context::get_state): New overload. (null_assignment_sm_context::set_next_state): New overload. (null_assignment_sm_context::get_diagnostic_tree): New. * engine.cc (impl_sm_context::get_state): New overload. (impl_sm_context::set_next_state): New overload. (impl_sm_context::get_diagnostic_tree): New overload. (impl_region_model_context::on_condition): Convert params from tree to const svalue *. * exploded-graph.h (impl_region_model_context::on_condition): Likewise. * region-model.cc (region_model::on_call_pre): Move handling of internal calls to before checking for get_fndecl_for_call. (region_model::add_constraints_from_binop): New. (region_model::add_constraint): Split out into a new overload working on const svalue * rather than tree. Call add_constraints_from_binop. Drop call to add_any_constraints_from_ssa_def_stmt. (region_model::add_any_constraints_from_ssa_def_stmt): Delete. (region_model::add_any_constraints_from_gassign): Delete. (region_model::add_any_constraints_from_gcall): Delete. * region-model.h (region_model::add_any_constraints_from_ssa_def_stmt): Delete. (region_model::add_any_constraints_from_gassign): Delete. (region_model::add_any_constraints_from_gcall): Delete. (region_model::add_constraint): Add overload decl. (region_model::add_constraints_from_binop): New decl. (region_model_context::on_condition): Convert params from tree to const svalue *. (noop_region_model_context::on_condition): Likewise. * sm-file.cc (fileptr_state_machine::condition): Likewise. * sm-malloc.cc (malloc_state_machine::on_condition): Likewise. * sm-pattern-test.cc: Include tristate.h, selftest.h, analyzer/call-string.h, analyzer/program-point.h, analyzer/store.h, and analyzer/region-model.h. (pattern_test_state_machine::on_condition): Convert params from tree to const svalue *. * sm-sensitive.cc (sensitive_state_machine::on_condition): Delete. * sm-signal.cc (signal_state_machine::on_condition): Delete. * sm-taint.cc (taint_state_machine::on_condition): Convert params from tree to const svalue *. * sm.cc: Include tristate.h, selftest.h, analyzer/call-string.h, analyzer/program-point.h, analyzer/store.h, and analyzer/region-model.h. (any_pointer_p): Add overload taking const svalue *sval. * sm.h (any_pointer_p): Add overload taking const svalue *sval. (state_machine::on_condition): Convert params from tree to const svalue *. Provide no-op default implementation. (sm_context::get_state): Add overload taking const svalue *sval. (sm_context::set_next_state): Likewise. (sm_context::on_transition): Likewise. (sm_context::get_diagnostic_tree): Likewise. * svalue.cc (svalue::all_zeroes_p): New. (constant_svalue::all_zeroes_p): New. (repeated_svalue::all_zeroes_p): Convert to vfunc. * svalue.h (svalue::all_zeroes_p): New decl. (constant_svalue::all_zeroes_p): New decl. (repeated_svalue::all_zeroes_p): Convert decl to vfunc. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/pattern-test-2.c: Update expected results. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_state_machine::on_condition): Remove. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2021-07-06Remove support for %G and %K.Martin Sebor1-1/+1
gcc/c-family/ChangeLog: * c-format.c (gcc_tdiag_char_table): Remove support for %G and %K. (gcc_cdiag_char_table): Same. (gcc_cxxdiag_char_table): Same. gcc/c/ChangeLog: * c-objc-common.c (c_tree_printer): Remove support for %G and %K. gcc/cp/ChangeLog: * error.c (cp_printer): Remove support for %G and %K. gcc/ChangeLog: * gimple-pretty-print.c (percent_G_format): Remove. * tree-diagnostic.c (default_tree_printer): Remove calls. * tree-pretty-print.c (percent_K_format): Remove. * tree-pretty-print.h (percent_K_format): Remove. gcc/testsuite/ChangeLog: * gcc.dg/format/gcc_diag-10.c: Update expected warnings. * gcc.dg/plugin/diagnostic_plugin_test_inlining.c: Remove %G.
2021-05-29diagnostics: Fix sporadic test failureBernd Edlinger5-0/+10
it turns out to be reproducible this way: COLUMNS=80 make check-gcc-c RUNTESTFLAGS="plugin.exp=diagnostic*" Running /home/ed/gnu/gcc-trunk/gcc/testsuite/gcc.dg/plugin/plugin.exp ... FAIL: gcc.dg/plugin/diagnostic-test-expressions-1.c -fplugin=./diagnostic_plugin_test_tree_expression_range.so 1 blank line(s) in output FAIL: gcc.dg/plugin/diagnostic-test-expressions-1.c -fplugin=./diagnostic_plugin_test_tree_expression_range.so expected multiline pattern lines 550-551 not found: " __builtin_types_compatible_p \(long, int\) \+ f \(i\)\);.*\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\^~~~~~~\n" FAIL: gcc.dg/plugin/diagnostic-test-expressions-1.c -fplugin=./diagnostic_plugin_test_tree_expression_range.so (test for excess errors) a lot more errors happen with COLUMNS=20. 2021-05-29 Bernd Edlinger <bernd.edlinger@hotmail.de> * gcc.dg/plugin/diagnostic_plugin_show_trees.c (plugin_init): Fix caret_max_with. * gcc.dg/plugin/diagnostic_plugin_test_inlining.c (plugin_init): Likewise. * gcc.dg/plugin/diagnostic_plugin_test_paths.c (plugin_init): Likewise. * gcc.dg/plugin/diagnostic_plugin_test_string_literals.c (plugin_init): Likewise. * gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.c (plugin_init): Likewise.
2021-01-19PR middle-end/98664 - inconsistent -Wfree-nonheap-object for inlined calls ↵Martin Sebor1-1/+2
to system headers gcc/ChangeLog: PR middle-end/98664 * tree-ssa-live.c (remove_unused_scope_block_p): Keep scopes for all functions, even if they're not declared artificial or inline. * tree.c (tree_inlined_location): Use macro expansion location only if scope traversal fails to expose one. gcc/testsuite/ChangeLog: PR middle-end/98664 * gcc.dg/Wvla-larger-than-4.c: Adjust expected output. * gcc.dg/plugin/diagnostic-test-inlining-3.c: Same. * g++.dg/warn/Wfree-nonheap-object-5.C: New test. * gcc.dg/Wfree-nonheap-object-4.c: New test.
2021-01-14Add GCC_EXTRA_DIAGNOSTIC_OUTPUT environment variable for fix-it hintsDavid Malcolm3-0/+144
GCC has had the ability to emit fix-it hints in machine-readable form since GCC 7 via -fdiagnostics-parseable-fixits and -fdiagnostics-generate-patch. The former emits additional specially-formatted lines to stderr; the option and its format were directly taken from a pre-existing option in clang. Ideally this could be used by IDEs so that the user can select specific fix-it hints and have the IDE apply them to the user's source code (perhaps turning them into clickable elements, perhaps with an "Apply All" option, etc). Eclipse CDT has supported this option in this way for a few years: https://bugs.eclipse.org/bugs/show_bug.cgi?id=497670 As a user of Emacs I would like Emacs to support such a feature. https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25987 tracks supporting GCC fix-it output in Emacs. The discussion there identifies two issues with the existing option: (a) columns in the output are specified as byte-offsets within the line (for exact compatibility with the option in clang), whereas emacs would prefer to consume them as what GCC 11 calls "display columns". https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html#index-fdiagnostics-column-unit (b) injecting a command-line option into the build is a fiddly manual step, varying between build systems. It's far easier for the user if Emacs simply sets an environment variable when compiling, GCC uses this to enable the option if it recognizes the value, and the emacs compilation buffer decodes the additional lines of output and adds appropriate widgets. In some ways it is a workaround for not having a language server. Doing it this way means that for the various combinations of older and newer GCC and older and newer Emacs that a sufficiently modern combination of both can automatically support the rich fix-it UI, whereas other combinations will either not provide the envvar, or silently ignore it, gracefully doing nothing extra. Hence this patch adds a new GCC_EXTRA_DIAGNOSTIC_OUTPUT environment variable to GCC which enables output of machine-parseable fix-it hints. GCC_EXTRA_DIAGNOSTIC_OUTPUT=fixits-v1 is equivalent to the existing -fdiagnostics-parseable-fixits option. GCC_EXTRA_DIAGNOSTIC_OUTPUT=fixits-v2 is the same, but changes the column output mode to "display columns" rather than bytes, as required by Emacs. The discussion in that Emacs bug has some concerns about the encoding of these lines, and, indeed, the encoding of GCC's stderr in general: currently we emit a mixture of bytes and UTF-8; I believe we emit filenames as bytes, diagnostic messages as UTF-8, and quote source code in the original encoding (PR other/93067 covers converting it to UTF-8 on output). This patch prints octal-escaped bytes for bytes within filenames and replacement text that aren't printable (as per -fdiagnostics-parseable-fixits). gcc/ChangeLog: * diagnostic.c (diagnostic_initialize): Eliminate parseable_fixits_p in favor of initializing extra_output_kind from GCC_EXTRA_DIAGNOSTIC_OUTPUT. (convert_column_unit): New function, split out from... (diagnostic_converted_column): ...this. (print_parseable_fixits): Add "column_unit" and "tabstop" params. Use them to call convert_column_unit on the column values. (diagnostic_report_diagnostic): Eliminate conditional on parseable_fixits_p in favor of a switch statement on extra_output_kind, passing the appropriate values to the new params of print_parseable_fixits. (selftest::test_print_parseable_fixits_none): Update for new params of print_parseable_fixits. (selftest::test_print_parseable_fixits_insert): Likewise. (selftest::test_print_parseable_fixits_remove): Likewise. (selftest::test_print_parseable_fixits_replace): Likewise. (selftest::test_print_parseable_fixits_bytes_vs_display_columns): New. (selftest::diagnostic_c_tests): Call it. * diagnostic.h (enum diagnostics_extra_output_kind): New. (diagnostic_context::parseable_fixits_p): Delete field in favor of... (diagnostic_context::extra_output_kind): ...this new field. * doc/invoke.texi (Environment Variables): Add GCC_EXTRA_DIAGNOSTIC_OUTPUT. * opts.c (common_handle_option): Update handling of OPT_fdiagnostics_parseable_fixits for change to diagnostic_context fields. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-show-locus-GCC_EXTRA_DIAGNOSTIC_OUTPUT-fixits-v1.c: New file. * gcc.dg/plugin/diagnostic-test-show-locus-GCC_EXTRA_DIAGNOSTIC_OUTPUT-fixits-v2.c: New file. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add them.
2021-01-07PR middle-end/98578 - ICE warning on uninitialized VLA accessMartin Sebor1-2/+2
gcc/c-family/ChangeLog: PR middle-end/98578 * c-pretty-print.c (print_mem_ref): Strip array from access type. Avoid assuming acces type's size is constant. Correct condition guarding the printing of a parenthesis. gcc/testsuite/ChangeLog: PR middle-end/98578 * gcc.dg/plugin/gil-1.c: Adjust expected output. * gcc.dg/uninit-pr98578.c: New test.
2021-01-04Update copyright years.Jakub Jelinek1-1/+1
2020-11-30Add analyzer plugin support and CPython GIL exampleDavid Malcolm4-0/+560
This patch adds a new GCC plugin event: PLUGIN_ANALYZER_INIT, called when -fanalyzer is starting, allowing for GCC plugins to register additional state-machine-based checks within -fanalyzer. The idea is that 3rd-party code might want to add domain-specific checks for its own APIs - with the caveat that the analyzer is itself still rather experimental. As an example, the patch adds a proof-of-concept plugin to the testsuite for checking CPython code: verifying that code that relinquishes CPython's global interpreter lock doesn't attempt to do anything with PyObjects in the sections where the lock isn't held. It also adds a warning about nested releases of the lock, which is forbidden. For example: demo.c: In function 'foo': demo.c:11:3: warning: use of PyObject '*(obj)' without the GIL 11 | Py_INCREF (obj); | ^~~~~~~~~ 'test': events 1-3 | | 15 | void test (PyObject *obj) | | ^~~~ | | | | | (1) entry to 'test' | 16 | { | 17 | Py_BEGIN_ALLOW_THREADS | | ~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) releasing the GIL here | 18 | foo (obj); | | ~~~~~~~~~ | | | | | (3) calling 'foo' from 'test' | +--> 'foo': events 4-5 | | 9 | foo (PyObject *obj) | | ^~~ | | | | | (4) entry to 'foo' | 10 | { | 11 | Py_INCREF (obj); | | ~~~~~~~~~ | | | | | (5) PyObject '*(obj)' used here without the GIL | Doing so requires adding some logic for ignoring macro expansions in analyzer diagnostics, since the insides of Py_INCREF and Py_BEGIN_ALLOW_THREADS are not of interest to the user for these cases. gcc/analyzer/ChangeLog: * analyzer-pass.cc (pass_analyzer::execute): Move sorry call to... (sorry_no_analyzer): New. * analyzer.h (class state_machine): New forward decl. (class logger): New forward decl. (class plugin_analyzer_init_iface): New. (sorry_no_analyzer): New decl. * checker-path.cc (checker_path::fixup_locations): New. * checker-path.h (checker_event::set_location): New. (checker_path::fixup_locations): New decl. * diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic): Call checker_path::fixup_locations, and call fixup_location on the primary location. * engine.cc: Include "plugin.h". (class plugin_analyzer_init_impl): New. (impl_run_checkers): Invoke PLUGIN_ANALYZER_INIT callbacks. * pending-diagnostic.h (pending_diagnostic::fixup_location): New vfunc. gcc/ChangeLog: * doc/plugins.texi (Plugin callbacks): Add PLUGIN_ANALYZER_INIT. * plugin.c (register_callback): Likewise. (invoke_plugin_callbacks_full): Likewise. * plugin.def (PLUGIN_ANALYZER_INIT): New event. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: New test. * gcc.dg/plugin/gil-1.c: New test. * gcc.dg/plugin/gil.h: New header. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new plugin and test.
2020-10-07Add -fdiagnostics-path-format=separate-events to -fdiagnostics-plain-outputDavid Malcolm4-147/+47
The path-printing default of -fdiagnostics-path-format=inline-events interacted poorly with -fdiagnostics-plain-output, so it makes most sense to add -fdiagnostics-path-format=separate-events to -fdiagnostics-plain-output. Seen when adding an experimental analyzer plugin to gcc.dg/plugin.exp. gcc/ChangeLog: * doc/invoke.texi (-fdiagnostics-plain-output): Add -fdiagnostics-path-format=separate-events to list of options injected by -fdiagnostics-plain-output. * opts-common.c (decode_cmdline_options_to_array): Likewise. gcc/testsuite/ChangeLog: * g++.dg/analyzer/analyzer.exp (DEFAULT_CXXFLAGS): Remove -fdiagnostics-path-format=separate-events. * gcc.dg/analyzer/analyzer.exp (DEFAULT_CFLAGS): Likewise. * gcc.dg/plugin/diagnostic-path-format-default.c: Rename to... * gcc.dg/plugin/diagnostic-path-format-plain.c: ...this. Remove dg-options directive. Copy remainder of test from diagnostic-path-format-separate-events.c. * gcc.dg/plugin/diagnostic-test-paths-2.c: Add -fdiagnostics-path-format=inline-events to options. Fix expected output for location of conditional within "for" loop. * gcc.dg/plugin/plugin.exp (plugin_test_list): Update for renaming. * gfortran.dg/analyzer/analyzer.exp (DEFAULT_FFLAGS): Remove -fdiagnostics-path-format=separate-events.
2020-07-14diagnostics: Support conversion of tabs to spaces [PR49973] [PR86904]Lewis Hyatt2-10/+10
Supports conversion of tabs to spaces when outputting diagnostics. Also adds -fdiagnostics-column-unit and -fdiagnostics-column-origin options to control how the column number is output, thereby resolving the two PRs. gcc/c-family/ChangeLog: PR other/86904 * c-indentation.c (should_warn_for_misleading_indentation): Get global tabstop from the new source. * c-opts.c (c_common_handle_option): Remove handling of -ftabstop, which is now a common option. * c.opt: Likewise. gcc/ChangeLog: PR preprocessor/49973 PR other/86904 * common.opt: Handle -ftabstop here instead of in c-family options. Add -fdiagnostics-column-unit= and -fdiagnostics-column-origin= options. * opts.c (common_handle_option): Handle the new options. * diagnostic-format-json.cc (json_from_expanded_location): Add diagnostic_context argument. Use it to convert column numbers as per the new options. (json_from_location_range): Likewise. (json_from_fixit_hint): Likewise. (json_end_diagnostic): Pass the new context argument to helper functions above. Add "column-origin" field to the output. (test_unknown_location): Add the new context argument to calls to helper functions. (test_bad_endpoints): Likewise. * diagnostic-show-locus.c (exploc_with_display_col::exploc_with_display_col): Support tabstop parameter. (layout_point::layout_point): Make use of class exploc_with_display_col. (layout_range::layout_range): Likewise. (struct line_bounds): Clarify that the units are now always display columns. Rename members accordingly. Add constructor. (layout::print_source_line): Add support for tab expansion. (make_range): Adapt to class layout_range changes. (layout::maybe_add_location_range): Likewise. (layout::layout): Adapt to class exploc_with_display_col changes. (layout::calculate_x_offset_display): Support tabstop parameter. (layout::print_annotation_line): Adapt to struct line_bounds changes. (layout::print_line): Likewise. (line_label::line_label): Add diagnostic_context argument. (get_affected_range): Likewise. (get_printed_columns): Likewise. (layout::print_any_labels): Adapt to struct line_label changes. (class correction): Add m_tabstop member. (correction::correction): Add tabstop argument. (correction::compute_display_cols): Use m_tabstop. (class line_corrections): Add m_context member. (line_corrections::line_corrections): Add diagnostic_context argument. (line_corrections::add_hint): Use m_context to handle tabstops. (layout::print_trailing_fixits): Adapt to class line_corrections changes. (test_layout_x_offset_display_utf8): Support tabstop parameter. (test_layout_x_offset_display_tab): New selftest. (test_one_liner_colorized_utf8): Likewise. (test_tab_expansion): Likewise. (test_diagnostic_show_locus_one_liner_utf8): Call the new tests. (diagnostic_show_locus_c_tests): Likewise. (test_overlapped_fixit_printing): Adapt to helper class and function changes. (test_overlapped_fixit_printing_utf8): Likewise. (test_overlapped_fixit_printing_2): Likewise. * diagnostic.h (enum diagnostics_column_unit): New enum. (struct diagnostic_context): Add members for the new options. (diagnostic_converted_column): Declare. (json_from_expanded_location): Add new context argument. * diagnostic.c (diagnostic_initialize): Initialize new members. (diagnostic_converted_column): New function. (maybe_line_and_column): Be willing to output a column of 0. (diagnostic_get_location_text): Convert column number as per the new options. (diagnostic_report_current_module): Likewise. (assert_location_text): Add origin and column_unit arguments for testing the new functionality. (test_diagnostic_get_location_text): Test the new functionality. * doc/invoke.texi: Document the new options and behavior. * input.h (location_compute_display_column): Add tabstop argument. * input.c (location_compute_display_column): Likewise. (test_cpp_utf8): Add selftests for tab expansion. * tree-diagnostic-path.cc (default_tree_make_json_for_path): Pass the new context argument to json_from_expanded_location(). libcpp/ChangeLog: PR preprocessor/49973 PR other/86904 * include/cpplib.h (struct cpp_options): Removed support for -ftabstop, which is now handled by diagnostic_context. (class cpp_display_width_computation): New class. (cpp_byte_column_to_display_column): Add optional tabstop argument. (cpp_display_width): Likewise. (cpp_display_column_to_byte_column): Likewise. * charset.c (cpp_display_width_computation::cpp_display_width_computation): New function. (cpp_display_width_computation::advance_display_cols): Likewise. (compute_next_display_width): Removed and implemented this functionality in a new function... (cpp_display_width_computation::process_next_codepoint): ...here. (cpp_byte_column_to_display_column): Added tabstop argument. Reimplemented in terms of class cpp_display_width_computation. (cpp_display_column_to_byte_column): Likewise. * init.c (cpp_create_reader): Remove handling of -ftabstop, which is now handled by diagnostic_context. gcc/testsuite/ChangeLog: PR preprocessor/49973 PR other/86904 * c-c++-common/Wmisleading-indentation-3.c: Adjust expected output for new defaults. * c-c++-common/Wmisleading-indentation.c: Likewise. * c-c++-common/diagnostic-format-json-1.c: Likewise. * c-c++-common/diagnostic-format-json-2.c: Likewise. * c-c++-common/diagnostic-format-json-3.c: Likewise. * c-c++-common/diagnostic-format-json-4.c: Likewise. * c-c++-common/diagnostic-format-json-5.c: Likewise. * c-c++-common/missing-close-symbol.c: Likewise. * g++.dg/diagnostic/bad-binary-ops.C: Likewise. * g++.dg/parse/error4.C: Likewise. * g++.old-deja/g++.brendan/crash11.C: Likewise. * g++.old-deja/g++.pt/overload2.C: Likewise. * g++.old-deja/g++.robertl/eb109.C: Likewise. * gcc.dg/analyzer/malloc-paths-9.c: Likewise. * gcc.dg/bad-binary-ops.c: Likewise. * gcc.dg/format/branch-1.c: Likewise. * gcc.dg/format/pr79210.c: Likewise. * gcc.dg/plugin/diagnostic-test-expressions-1.c: Likewise. * gcc.dg/plugin/diagnostic-test-string-literals-1.c: Likewise. * gcc.dg/redecl-4.c: Likewise. * gfortran.dg/diagnostic-format-json-1.F90: Likewise. * gfortran.dg/diagnostic-format-json-2.F90: Likewise. * gfortran.dg/diagnostic-format-json-3.F90: Likewise. * go.dg/arrayclear.go: Add a comment explaining why adding a comment was necessary to work around a dejagnu bug. * c-c++-common/diagnostic-units-1.c: New test. * c-c++-common/diagnostic-units-2.c: New test. * c-c++-common/diagnostic-units-3.c: New test. * c-c++-common/diagnostic-units-4.c: New test. * c-c++-common/diagnostic-units-5.c: New test. * c-c++-common/diagnostic-units-6.c: New test. * c-c++-common/diagnostic-units-7.c: New test. * c-c++-common/diagnostic-units-8.c: New test.
2020-05-06add a new option -flarge-source-files.qing zhao1-1/+1
gcc/ChangeLog: PR c/94230 * common.opt: Add -flarge-source-files. * doc/invoke.texi: Document it. * toplev.c (process_options): set line_table->default_range_bits to 0 when flag_large_source_files is true. gcc/c-family/ChangeLog: PR c/94230 * c-indentation.c (get_visual_column): Add a hint to use the new -flarge-source-files option. gcc/testsuite/ChangeLog: PR c/94230 * gcc.dg/plugin/location-overflow-test-1.c (fn_1): New message to provide hint to use the new -flarge-source-files option.
2020-01-28diagnostic_metadata: unbreak xgettext (v2)David Malcolm2-8/+9
Changed in v2: - rename from warning_with_metadata_at to warning_meta - fix test plugins While C++ can have overloads, xgettext can't deal with overloads that have different argument positions, leading to two failures in "make gcc.pot": emit_diagnostic_valist used incompatibly as both --keyword=emit_diagnostic_valist:4 --flag=emit_diagnostic_valist:4:gcc-internal-format and --keyword=emit_diagnostic_valist:5 --flag=emit_diagnostic_valist:5:gcc-internal-format warning_at used incompatibly as both --keyword=warning_at:3 --flag=warning_at:3:gcc-internal-format and --keyword=warning_at:4 --flag=warning_at:4:gcc-internal-format The emit_diagnostic_valist overload isn't used anywhere (I think it's a leftover from an earlier iteration of the analyzer patch kit). The warning_at overload is used throughout the analyzer but nowhere else. Ideally I'd like to consolidate this argument with something constructable in various ways: - from a metadata and an int or - from an int (or, better an "enum opt_code"), so that the overload happens when implicitly choosing the ctor, but that feels like stage 1 material. In the meantime, fix xgettext by deleting the unused overload and renaming the used one. gcc/analyzer/ChangeLog: * region-model.cc (poisoned_value_diagnostic::emit): Update for renaming of warning_at overload to warning_meta. * sm-file.cc (file_leak::emit): Likewise. * sm-malloc.cc (double_free::emit): Likewise. (possible_null_deref::emit): Likewise. (possible_null_arg::emit): Likewise. (null_deref::emit): Likewise. (null_arg::emit): Likewise. (use_after_free::emit): Likewise. (malloc_leak::emit): Likewise. (free_of_non_heap::emit): Likewise. * sm-sensitive.cc (exposure_through_output_file::emit): Likewise. * sm-signal.cc (signal_unsafe_call::emit): Likewise. * sm-taint.cc (tainted_array_index::emit): Likewise. gcc/ChangeLog: * diagnostic-core.h (warning_at): Rename overload to... (warning_meta): ...this. (emit_diagnostic_valist): Delete decl of overload taking diagnostic_metadata. * diagnostic.c (emit_diagnostic_valist): Likewise for defn. (warning_at): Rename overload taking diagnostic_metadata to... (warning_meta): ...this. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic_plugin_test_metadata.c: Update for renaming of warning_at overload to warning_meta. * gcc.dg/plugin/diagnostic_plugin_test_paths.c: Likewise.
2020-01-13testsuite: remove unused dg-line directiveDavid Malcolm1-1/+1
gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-paths-2.c: Remove unused dg-line directive.
2020-01-10Add diagnostic pathsDavid Malcolm12-0/+1366
This patch adds support for associating a "diagnostic_path" with a diagnostic: a sequence of events predicted by the compiler that leads to the problem occurring, with their locations in the user's source, text descriptions, and stack information (for handling interprocedural paths). For example, the following (hypothetical) error has a 3-event intraprocedural path: test.c: In function 'demo': test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter 29 | PyList_Append(list, item); | ^~~~~~~~~~~~~~~~~~~~~~~~~ 'demo': events 1-3 | | 25 | list = PyList_New(0); | | ^~~~~~~~~~~~~ | | | | | (1) when 'PyList_New' fails, returning NULL | 26 | | 27 | for (i = 0; i < count; i++) { | | ~~~ | | | | | (2) when 'i < count' | 28 | item = PyLong_FromLong(random()); | 29 | PyList_Append(list, item); | | ~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1 | The patch adds a new "%@" format code for printing event IDs, so that in the above, the description of event (3) mentions event (1), showing the user where the bogus NULL value comes from (the event IDs are colorized to draw the user's attention to them). There is a separation between data vs presentation: the above shows how the diagnostic-printing code has consolidated the path into a single run of events, since all the events are near each other and within the same function; more complicated examples (such as interprocedural paths) might be printed as multiple runs of events. Examples of how interprocedural paths are printed can be seen in the test suite (which uses a plugin to exercise the code without relying on specific warnings using this functionality). Other output formats include - JSON, - printing each event as a separate "note", and - to not emit paths. gcc/ChangeLog: * Makefile.in (OBJS): Add tree-diagnostic-path.o. * common.opt (fdiagnostics-path-format=): New option. (diagnostic_path_format): New enum. (fdiagnostics-show-path-depths): New option. * coretypes.h (diagnostic_event_id_t): New forward decl. * diagnostic-color.c (color_dict): Add "path". * diagnostic-event-id.h: New file. * diagnostic-format-json.cc (json_from_expanded_location): Make non-static. (json_end_diagnostic): Call context->make_json_for_path if it exists and the diagnostic has a path. (diagnostic_output_format_init): Clear context->print_path. * diagnostic-path.h: New file. * diagnostic-show-locus.c (colorizer::set_range): Special-case when printing a run of events in a diagnostic_path so that they all get the same color. (layout::m_diagnostic_path_p): New field. (layout::layout): Initialize it. (layout::print_any_labels): Don't colorize the label text for an event in a diagnostic_path. (gcc_rich_location::add_location_if_nearby): Add "restrict_to_current_line_spans" and "label" params. Pass the former to layout.maybe_add_location_range; pass the latter when calling add_range. * diagnostic.c: Include "diagnostic-path.h". (diagnostic_initialize): Initialize context->path_format and context->show_path_depths. (diagnostic_show_any_path): New function. (diagnostic_path::interprocedural_p): New function. (diagnostic_report_diagnostic): Call diagnostic_show_any_path. (simple_diagnostic_path::num_events): New function. (simple_diagnostic_path::get_event): New function. (simple_diagnostic_path::add_event): New function. (simple_diagnostic_event::simple_diagnostic_event): New ctor. (simple_diagnostic_event::~simple_diagnostic_event): New dtor. (debug): New overload taking a diagnostic_path *. * diagnostic.def (DK_DIAGNOSTIC_PATH): New. * diagnostic.h (enum diagnostic_path_format): New enum. (json::value): New forward decl. (diagnostic_context::path_format): New field. (diagnostic_context::show_path_depths): New field. (diagnostic_context::print_path): New callback field. (diagnostic_context::make_json_for_path): New callback field. (diagnostic_show_any_path): New decl. (json_from_expanded_location): New decl. * doc/invoke.texi (-fdiagnostics-path-format=): New option. (-fdiagnostics-show-path-depths): New option. (-fdiagnostics-color): Add "path" to description of default GCC_COLORS; describe it. (-fdiagnostics-format=json): Document how diagnostic paths are represented in the JSON output format. * gcc-rich-location.h (gcc_rich_location::add_location_if_nearby): Add optional params "restrict_to_current_line_spans" and "label". * opts.c (common_handle_option): Handle OPT_fdiagnostics_path_format_ and OPT_fdiagnostics_show_path_depths. * pretty-print.c: Include "diagnostic-event-id.h". (pp_format): Implement "%@" format code for printing diagnostic_event_id_t *. (selftest::test_pp_format): Add tests for "%@". * selftest-run-tests.c (selftest::run_tests): Call selftest::tree_diagnostic_path_cc_tests. * selftest.h (selftest::tree_diagnostic_path_cc_tests): New decl. * toplev.c (general_init): Initialize global_dc->path_format and global_dc->show_path_depths. * tree-diagnostic-path.cc: New file. * tree-diagnostic.c (maybe_unwind_expanded_macro_loc): Make non-static. Drop "diagnostic" param in favor of storing the original value of "where" and re-using it. (virt_loc_aware_diagnostic_finalizer): Update for dropped param of maybe_unwind_expanded_macro_loc. (tree_diagnostics_defaults): Initialize context->print_path and context->make_json_for_path. * tree-diagnostic.h (default_tree_diagnostic_path_printer): New decl. (default_tree_make_json_for_path): New decl. (maybe_unwind_expanded_macro_loc): New decl. gcc/c-family/ChangeLog: * c-format.c (local_event_ptr_node): New. (PP_FORMAT_CHAR_TABLE): Add entry for "%@". (init_dynamic_diag_info): Initialize local_event_ptr_node. * c-format.h (T_EVENT_PTR): New define. gcc/testsuite/ChangeLog: * gcc.dg/format/gcc_diag-10.c (diagnostic_event_id_t): New typedef. (test_diag): Add coverage of "%@". * gcc.dg/plugin/diagnostic-path-format-default.c: New test. * gcc.dg/plugin/diagnostic-path-format-inline-events-1.c: New test. * gcc.dg/plugin/diagnostic-path-format-inline-events-2.c: New test. * gcc.dg/plugin/diagnostic-path-format-inline-events-3.c: New test. * gcc.dg/plugin/diagnostic-path-format-none.c: New test. * gcc.dg/plugin/diagnostic-test-paths-1.c: New test. * gcc.dg/plugin/diagnostic-test-paths-2.c: New test. * gcc.dg/plugin/diagnostic-test-paths-3.c: New test. * gcc.dg/plugin/diagnostic-test-paths-4.c: New test. * gcc.dg/plugin/diagnostic_plugin_test_paths.c: New. * gcc.dg/plugin/plugin.exp: Add the new plugin and test cases. libcpp/ChangeLog: * include/line-map.h (class diagnostic_path): New forward decl. (rich_location::get_path): New accessor. (rich_location::set_path): New function. (rich_location::m_path): New field. * line-map.c (rich_location::rich_location): Initialize m_path. From-SVN: r280142
2020-01-01Update copyright years.Jakub Jelinek1-1/+1
From-SVN: r279813
2019-12-18Add diagnostic_metadata and CWE supportDavid Malcolm3-0/+150
This patch adds support for associating a diagnostic message with an optional diagnostic_metadata object, so that plugins can add extra data to their diagnostics (e.g. mapping a diagnostic to a taxonomy or coding standard such as from CERT or MISRA). Currently this only supports associating a CWE identifier with a diagnostic (which is what I'm using for the warnings in the analyzer patch kit), but adding a diagnostic_metadata class allows for future growth in this area without an explosion of further "warning_at" overloads for all of the different kinds of custom data that a plugin might want to add. This version of the patch renames the overly-general -fdiagnostics-show-metadata to -fdiagnostics-show-cwe and adds test coverage for it via a plugin. It also adds a note to the documentation that no GCC diagnostics currently use this; it's a feature for plugins (and, at some point, I hope, the analyzer). gcc/ChangeLog: * common.opt (fdiagnostics-show-cwe): Add. * diagnostic-core.h (class diagnostic_metadata): New forward decl. (warning_at): Add overload taking a const diagnostic_metadata &. (emit_diagnostic_valist): Add overload taking a const diagnostic_metadata *. * diagnostic-format-json.cc: Include "diagnostic-metadata.h". (json_from_metadata): New function. (json_end_diagnostic): Call it to add "metadata" child for diagnostics with metadata. (diagnostic_output_format_init): Clear context->show_cwe. * diagnostic-metadata.h: New file. * diagnostic.c: Include "diagnostic-metadata.h". (diagnostic_impl): Add const diagnostic_metadata * param. (diagnostic_n_impl): Likewise. (diagnostic_initialize): Initialize context->show_cwe. (diagnostic_set_info_translated): Initialize diagnostic->metadata. (get_cwe_url): New function. (print_any_cwe): New function. (diagnostic_report_diagnostic): Call print_any_cwe if the diagnostic has non-NULL metadata. (emit_diagnostic): Pass NULL as the metadata in the call to diagnostic_impl. (emit_diagnostic_valist): Likewise. (emit_diagnostic_valist): New overload taking a const diagnostic_metadata *. (inform): Pass NULL as the metadata in the call to diagnostic_impl. (inform_n): Likewise for diagnostic_n_impl. (warning): Likewise. (warning_at): Likewise. Add overload that takes a const diagnostic_metadata &. (warning_n): Pass NULL as the metadata in the call to diagnostic_n_impl. (pedwarn): Likewise for diagnostic_impl. (permerror): Likewise. (error): Likewise. (error_n): Likewise. (error_at): Likewise. (sorry): Likewise. (sorry_at): Likewise. (fatal_error): Likewise. (internal_error): Likewise. (internal_error_no_backtrace): Likewise. * diagnostic.h (diagnostic_info::metadata): New field. (diagnostic_context::show_cwe): New field. * doc/invoke.texi (-fno-diagnostics-show-cwe): New option. * opts.c (common_handle_option): Handle OPT_fdiagnostics_show_cwe. * toplev.c (general_init): Initialize global_dc->show_cwe. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-metadata.c: New test. * gcc.dg/plugin/diagnostic_plugin_test_metadata.c: New test plugin. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add them. From-SVN: r279556