From 12b67d1e13b3cf14fb24cf2a1c008b73d377ff6d Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 1 Dec 2023 08:47:41 -0500 Subject: [PATCH] diagnostics, analyzer: add optional per-diagnostic property bags to SARIF I've found it useful in debugging the analyzer for the SARIF output to contain extra analyzer-specific data in each diagnostic. This patch: * adds a way for a diagnostic_metadata to populate a property bag within a SARIF "result" object based on a new vfunc * reworks how diagnostics are emitted within the analyzer so that a custom diagnostic_metadata subclass is used, which populates the property bag with information from the saved_diagnostic, and with a vfunc hook allowing for per-pending_diagnotic-subclass extra properties. Doing so makes it trivial to go from the SARIF output back to pertinent parts of the analyzer's internals (e.g. the index of the diagnostic within the ana::diagnostic_manager, the index of the ana::exploded_node, etc). It also replaces a lot of boilerplate in the "emit" implementations in the various pending_diagnostics subclasses. In particular, doing so fixes missing CVE metadata for -Wanalyzer-fd-phase-mismatch (where sm-fd.cc's fd_phase_mismatch::emit was failing to use its diagnostic_metadata instance). gcc/analyzer/ChangeLog: * analyzer.h (class saved_diagnostic): New forward decl. * bounds-checking.cc: Update for changes to pending_diagnostic::emit. * call-details.cc: Likewise. * diagnostic-manager.cc: Include "diagnostic-format-sarif.h". (saved_diagnostic::maybe_add_sarif_properties): New. (class pending_diagnostic_metadata): New. (diagnostic_manager::emit_saved_diagnostic): Create a pending_diagnostic_metadata and a diagnostic_emission_context. Pass the latter to the pending_diagnostic::emit vfunc. * diagnostic-manager.h (saved_diagnostic::maybe_add_sarif_properties): New decl. * engine.cc: Update for changes to pending_diagnostic::emit. * infinite-loop.cc: Likewise. * infinite-recursion.cc: Likewise. * kf-analyzer.cc: Likewise. * kf.cc: Likewise. * pending-diagnostic.cc (diagnostic_emission_context::get_pending_diagnostic): New. (diagnostic_emission_context::warn): New. (diagnostic_emission_context::inform): New. * pending-diagnostic.h (class diagnostic_emission_context): New. (pending_diagnostic::emit): Update params. (pending_diagnostic::maybe_add_sarif_properties): New vfunc. * region.cc: Don't include "diagnostic-metadata.h". * region-model.cc: Include "diagnostic-format-sarif.h". Update for changes to pending_diagnostic::emit. (exposure_through_uninit_copy::maybe_add_sarif_properties): New. * sm-fd.cc: Update for changes to pending_diagnostic::emit. * sm-file.cc: Likewise. * sm-malloc.cc: Likewise. * sm-pattern-test.cc: Likewise. * sm-sensitive.cc: Likewise. * sm-signal.cc: Likewise. * sm-taint.cc: Likewise. * store.cc: Don't include "diagnostic-metadata.h". * varargs.cc: Update for changes to pending_diagnostic::emit. gcc/ChangeLog: * diagnostic-core.h (emit_diagnostic_valist): New overload decl. * diagnostic-format-sarif.cc (sarif_builder::make_result_object): When we have metadata, call its maybe_add_sarif_properties vfunc. * diagnostic-metadata.h (class sarif_object): Forward decl. (diagnostic_metadata::~diagnostic_metadata): New. (diagnostic_metadata::maybe_add_sarif_properties): New vfunc. * diagnostic.cc (emit_diagnostic_valist): New overload. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/fd-accept.c: Update for fix to missing CWE metadata for -Wanalyzer-fd-phase-mismatch. * gcc.dg/analyzer/fd-bind.c: Likewise. * gcc.dg/analyzer/fd-socket-misuse.c: Likewise. * gcc.dg/plugin/analyzer_cpython_plugin.c: Update for changes to pending_diagnostic::emit. * gcc.dg/plugin/analyzer_gil_plugin.c: Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer.h | 1 + gcc/analyzer/bounds-checking.cc | 130 +++++------ gcc/analyzer/call-details.cc | 8 +- gcc/analyzer/diagnostic-manager.cc | 53 ++++- gcc/analyzer/diagnostic-manager.h | 2 + gcc/analyzer/engine.cc | 15 +- gcc/analyzer/infinite-loop.cc | 9 +- gcc/analyzer/infinite-recursion.cc | 9 +- gcc/analyzer/kf-analyzer.cc | 4 +- gcc/analyzer/kf.cc | 32 ++- gcc/analyzer/pending-diagnostic.cc | 45 ++++ gcc/analyzer/pending-diagnostic.h | 56 ++++- gcc/analyzer/region-model.cc | 123 +++++----- gcc/analyzer/region.cc | 1 - gcc/analyzer/sm-fd.cc | 75 +++---- gcc/analyzer/sm-file.cc | 23 +- gcc/analyzer/sm-malloc.cc | 118 ++++------ gcc/analyzer/sm-pattern-test.cc | 8 +- gcc/analyzer/sm-sensitive.cc | 12 +- gcc/analyzer/sm-signal.cc | 11 +- gcc/analyzer/sm-taint.cc | 212 ++++++++---------- gcc/analyzer/store.cc | 1 - gcc/analyzer/varargs.cc | 39 ++-- gcc/diagnostic-core.h | 6 + gcc/diagnostic-format-sarif.cc | 22 +- gcc/diagnostic-metadata.h | 10 + gcc/diagnostic.cc | 12 + gcc/testsuite/gcc.dg/analyzer/fd-accept.c | 2 +- gcc/testsuite/gcc.dg/analyzer/fd-bind.c | 4 +- .../gcc.dg/analyzer/fd-socket-misuse.c | 2 +- .../gcc.dg/plugin/analyzer_cpython_plugin.c | 10 +- .../gcc.dg/plugin/analyzer_gil_plugin.c | 28 +-- 32 files changed, 550 insertions(+), 533 deletions(-) diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index cf32d4b85b15..3115f878573a 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -94,6 +94,7 @@ class bounded_ranges_manager; struct pending_location; class pending_diagnostic; class pending_note; +class saved_diagnostic; struct event_loc_info; class checker_event; class state_change_event; diff --git a/gcc/analyzer/bounds-checking.cc b/gcc/analyzer/bounds-checking.cc index 583b5ab36a04..cc43ecc54683 100644 --- a/gcc/analyzer/bounds-checking.cc +++ b/gcc/analyzer/bounds-checking.cc @@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "gimple-iterator.h" #include "diagnostic-core.h" -#include "diagnostic-metadata.h" #include "diagnostic-diagram.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" @@ -119,10 +118,10 @@ protected: } void - maybe_show_notes (location_t loc, logger *logger) const + maybe_show_notes (diagnostic_emission_context &ctxt) const { - maybe_describe_array_bounds (loc); - maybe_show_diagram (logger); + maybe_describe_array_bounds (ctxt.get_location ()); + maybe_show_diagram (ctxt.get_logger ()); } /* Potentially add a note about valid ways to index this array, such @@ -281,27 +280,22 @@ public: return "concrete_buffer_overflow"; } - bool emit (rich_location *rich_loc, - logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; bool warned; switch (get_memory_space ()) { default: - m.add_cwe (787); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "buffer overflow"); + ctxt.add_cwe (787); + warned = ctxt.warn ("buffer overflow"); break; case MEMSPACE_STACK: - m.add_cwe (121); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "stack-based buffer overflow"); + ctxt.add_cwe (121); + warned = ctxt.warn ("stack-based buffer overflow"); break; case MEMSPACE_HEAP: - m.add_cwe (122); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "heap-based buffer overflow"); + ctxt.add_cwe (122); + warned = ctxt.warn ("heap-based buffer overflow"); break; } @@ -312,25 +306,25 @@ public: unsigned HOST_WIDE_INT num_bad_bytes = m_out_of_bounds_range.m_size_in_bytes.to_uhwi (); if (m_diag_arg) - inform_n (rich_loc->get_loc (), + inform_n (ctxt.get_location (), num_bad_bytes, "write of %wu byte to beyond the end of %qE", "write of %wu bytes to beyond the end of %qE", num_bad_bytes, m_diag_arg); else - inform_n (rich_loc->get_loc (), + inform_n (ctxt.get_location (), num_bad_bytes, "write of %wu byte to beyond the end of the region", "write of %wu bytes to beyond the end of the region", num_bad_bytes); } else if (m_diag_arg) - inform (rich_loc->get_loc (), + inform (ctxt.get_location (), "write to beyond the end of %qE", m_diag_arg); - maybe_show_notes (rich_loc->get_loc (), logger); + maybe_show_notes (ctxt); } return warned; @@ -388,24 +382,20 @@ public: return "concrete_buffer_over_read"; } - bool emit (rich_location *rich_loc, logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; bool warned; - m.add_cwe (126); + ctxt.add_cwe (126); switch (get_memory_space ()) { default: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "buffer over-read"); + warned = ctxt.warn ("buffer over-read"); break; case MEMSPACE_STACK: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "stack-based buffer over-read"); + warned = ctxt.warn ("stack-based buffer over-read"); break; case MEMSPACE_HEAP: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "heap-based buffer over-read"); + warned = ctxt.warn ("heap-based buffer over-read"); break; } @@ -416,25 +406,25 @@ public: unsigned HOST_WIDE_INT num_bad_bytes = m_out_of_bounds_range.m_size_in_bytes.to_uhwi (); if (m_diag_arg) - inform_n (rich_loc->get_loc (), + inform_n (ctxt.get_location (), num_bad_bytes, "read of %wu byte from after the end of %qE", "read of %wu bytes from after the end of %qE", num_bad_bytes, m_diag_arg); else - inform_n (rich_loc->get_loc (), + inform_n (ctxt.get_location (), num_bad_bytes, "read of %wu byte from after the end of the region", "read of %wu bytes from after the end of the region", num_bad_bytes); } else if (m_diag_arg) - inform (rich_loc->get_loc (), + inform (ctxt.get_location (), "read from after the end of %qE", m_diag_arg); - maybe_show_notes (rich_loc->get_loc (), logger); + maybe_show_notes (ctxt); } return warned; @@ -493,28 +483,24 @@ public: return "concrete_buffer_underwrite"; } - bool emit (rich_location *rich_loc, logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; bool warned; - m.add_cwe (124); + ctxt.add_cwe (124); switch (get_memory_space ()) { default: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "buffer underwrite"); + warned = ctxt.warn ("buffer underwrite"); break; case MEMSPACE_STACK: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "stack-based buffer underwrite"); + warned = ctxt.warn ("stack-based buffer underwrite"); break; case MEMSPACE_HEAP: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "heap-based buffer underwrite"); + warned = ctxt.warn ("heap-based buffer underwrite"); break; } if (warned) - maybe_show_notes (rich_loc->get_loc (), logger); + maybe_show_notes (ctxt); return warned; } @@ -568,28 +554,24 @@ public: return "concrete_buffer_under_read"; } - bool emit (rich_location *rich_loc, logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; bool warned; - m.add_cwe (127); + ctxt.add_cwe (127); switch (get_memory_space ()) { default: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "buffer under-read"); + warned = ctxt.warn ("buffer under-read"); break; case MEMSPACE_STACK: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "stack-based buffer under-read"); + warned = ctxt.warn ("stack-based buffer under-read"); break; case MEMSPACE_HEAP: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "heap-based buffer under-read"); + warned = ctxt.warn ("heap-based buffer under-read"); break; } if (warned) - maybe_show_notes (rich_loc->get_loc (), logger); + maybe_show_notes (ctxt); return warned; } @@ -679,30 +661,26 @@ public: return "symbolic_buffer_overflow"; } - bool emit (rich_location *rich_loc, logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; bool warned; switch (get_memory_space ()) { default: - m.add_cwe (787); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "buffer overflow"); + ctxt.add_cwe (787); + warned = ctxt.warn ("buffer overflow"); break; case MEMSPACE_STACK: - m.add_cwe (121); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "stack-based buffer overflow"); + ctxt.add_cwe (121); + warned = ctxt.warn ("stack-based buffer overflow"); break; case MEMSPACE_HEAP: - m.add_cwe (122); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "heap-based buffer overflow"); + ctxt.add_cwe (122); + warned = ctxt.warn ("heap-based buffer overflow"); break; } if (warned) - maybe_show_notes (rich_loc->get_loc (), logger); + maybe_show_notes (ctxt); return warned; } @@ -796,31 +774,27 @@ public: return "symbolic_buffer_over_read"; } - bool emit (rich_location *rich_loc, logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; - m.add_cwe (126); + ctxt.add_cwe (126); bool warned; switch (get_memory_space ()) { default: - m.add_cwe (787); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "buffer over-read"); + ctxt.add_cwe (787); + warned = ctxt.warn ("buffer over-read"); break; case MEMSPACE_STACK: - m.add_cwe (121); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "stack-based buffer over-read"); + ctxt.add_cwe (121); + warned = ctxt.warn ("stack-based buffer over-read"); break; case MEMSPACE_HEAP: - m.add_cwe (122); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "heap-based buffer over-read"); + ctxt.add_cwe (122); + warned = ctxt.warn ("heap-based buffer over-read"); break; } if (warned) - maybe_show_notes (rich_loc->get_loc (), logger); + maybe_show_notes (ctxt); return warned; } diff --git a/gcc/analyzer/call-details.cc b/gcc/analyzer/call-details.cc index 9480f037eaac..c5ae2dcb13ad 100644 --- a/gcc/analyzer/call-details.cc +++ b/gcc/analyzer/call-details.cc @@ -445,14 +445,12 @@ public: return OPT_Wanalyzer_overlapping_buffers; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; - bool warned; - warned = warning_at (rich_loc, get_controlling_option (), - "overlapping buffers passed as arguments to %qD", - m_fndecl); + bool warned = ctxt.warn ("overlapping buffers passed as arguments to %qD", + m_fndecl); // TODO: draw a picture? diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index a6755f2193fe..ecd57376b549 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/checker-path.h" #include "analyzer/reachability.h" #include "make-unique.h" +#include "diagnostic-format-sarif.h" #if ENABLE_ANALYZER @@ -1018,6 +1019,31 @@ saved_diagnostic::emit_any_notes () const pn->emit (); } +/* For SARIF output, add additional properties to the "result" object + for this diagnostic. + This extra data is intended for use when debugging the analyzer. */ + +void +saved_diagnostic::maybe_add_sarif_properties (sarif_object &result_obj) const +{ + sarif_property_bag &props = result_obj.get_or_create_properties (); +#define PROPERTY_PREFIX "gcc/analyzer/saved_diagnostic/" + if (m_sm) + props.set_string (PROPERTY_PREFIX "sm", m_sm->get_name ()); + props.set_integer (PROPERTY_PREFIX "enode", m_enode->m_index); + props.set_integer (PROPERTY_PREFIX "snode", m_snode->m_index); + if (m_sval) + props.set (PROPERTY_PREFIX "sval", m_sval->to_json ()); + if (m_state) + props.set (PROPERTY_PREFIX "state", m_state->to_json ()); + if (m_best_epath) + props.set (PROPERTY_PREFIX "idx", new json::integer_number (m_idx)); +#undef PROPERTY_PREFIX + + /* Potentially add pending_diagnostic-specific properties. */ + m_d->maybe_add_sarif_properties (result_obj); +} + /* State for building a checker_path from a particular exploded_path. In particular, this precomputes reachability information: the set of source enodes for which a path be found to the diagnostic enode. */ @@ -1498,6 +1524,29 @@ diagnostic_manager::emit_saved_diagnostics (const exploded_graph &eg) best_candidates.emit_best (this, eg); } +/* Custom subclass of diagnostic_metadata which, for SARIF output, + populates the property bag of the diagnostic's "result" object + with information from the saved_diagnostic and the + pending_diagnostic. */ + +class pending_diagnostic_metadata : public diagnostic_metadata +{ +public: + pending_diagnostic_metadata (const saved_diagnostic &sd) + : m_sd (sd) + { + } + + void + maybe_add_sarif_properties (sarif_object &result_obj) const override + { + m_sd.maybe_add_sarif_properties (result_obj); + } + +private: + const saved_diagnostic &m_sd; +}; + /* Given a saved_diagnostic SD with m_best_epath through EG, create an checker_path of suitable events and use it to call SD's underlying pending_diagnostic "emit" vfunc to emit a diagnostic. */ @@ -1563,7 +1612,9 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg, auto_diagnostic_group d; auto_cfun sentinel (sd.m_snode->m_fun); - if (sd.m_d->emit (&rich_loc, get_logger ())) + pending_diagnostic_metadata m (sd); + diagnostic_emission_context diag_ctxt (sd, rich_loc, m, get_logger ()); + if (sd.m_d->emit (diag_ctxt)) { sd.emit_any_notes (); diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h index 27ab9ed068eb..b6d6f087732b 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -67,6 +67,8 @@ public: void emit_any_notes () const; + void maybe_add_sarif_properties (sarif_object &result_obj) const; + //private: const state_machine *m_sm; const exploded_node *m_enode; diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index b4e855fcf24a..1f930a21eb37 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1811,13 +1811,11 @@ public: return OPT_Wanalyzer_stale_setjmp_buffer; } - bool emit (rich_location *richloc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at - (richloc, get_controlling_option (), - "%qs called after enclosing function of %qs has returned", - get_user_facing_name (m_longjmp_call), - get_user_facing_name (m_setjmp_call)); + return ctxt.warn ("%qs called after enclosing function of %qs has returned", + get_user_facing_name (m_longjmp_call), + get_user_facing_name (m_setjmp_call)); } const char *get_kind () const final override @@ -3982,10 +3980,9 @@ public: return OPT_Wanalyzer_jump_through_null; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at (rich_loc, get_controlling_option (), - "jump through null pointer"); + return ctxt.warn ("jump through null pointer"); } label_text describe_final_event (const evdesc::final_event &ev) final override diff --git a/gcc/analyzer/infinite-loop.cc b/gcc/analyzer/infinite-loop.cc index 771d698a60b7..c47ce1c89085 100644 --- a/gcc/analyzer/infinite-loop.cc +++ b/gcc/analyzer/infinite-loop.cc @@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "diagnostic-event-id.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "function.h" #include "pretty-print.h" #include "sbitmap.h" @@ -178,13 +177,11 @@ public: return OPT_Wanalyzer_infinite_loop; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* "CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop')". */ - diagnostic_metadata m; - m.add_cwe (835); - return warning_meta (rich_loc, m, get_controlling_option (), - "infinite loop"); + ctxt.add_cwe (835); + return ctxt.warn ("infinite loop"); } bool maybe_add_custom_events_for_superedge (const exploded_edge &, diff --git a/gcc/analyzer/infinite-recursion.cc b/gcc/analyzer/infinite-recursion.cc index 9576ff5f58db..0fab9b702a85 100644 --- a/gcc/analyzer/infinite-recursion.cc +++ b/gcc/analyzer/infinite-recursion.cc @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "diagnostic-event-id.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "function.h" #include "pretty-print.h" #include "sbitmap.h" @@ -95,13 +94,11 @@ public: return OPT_Wanalyzer_infinite_recursion; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* "CWE-674: Uncontrolled Recursion". */ - diagnostic_metadata m; - m.add_cwe (674); - return warning_meta (rich_loc, m, get_controlling_option (), - "infinite recursion"); + ctxt.add_cwe (674); + return ctxt.warn ("infinite recursion"); } label_text describe_final_event (const evdesc::final_event &ev) final override diff --git a/gcc/analyzer/kf-analyzer.cc b/gcc/analyzer/kf-analyzer.cc index 7ae598a89123..01e2c46d5ad5 100644 --- a/gcc/analyzer/kf-analyzer.cc +++ b/gcc/analyzer/kf-analyzer.cc @@ -255,9 +255,9 @@ public: return 0; } - bool emit (rich_location *richloc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - inform (richloc, "path"); + ctxt.inform ("path"); return true; } diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc index 5d8e04d97263..a69f084bbf3f 100644 --- a/gcc/analyzer/kf.cc +++ b/gcc/analyzer/kf.cc @@ -719,32 +719,29 @@ public: return OPT_Wanalyzer_putenv_of_auto_var; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; - diagnostic_metadata m; /* SEI CERT C Coding Standard: "POS34-C. Do not call putenv() with a pointer to an automatic variable as the argument". */ diagnostic_metadata::precanned_rule rule ("POS34-C", "https://wiki.sei.cmu.edu/confluence/x/6NYxBQ"); - m.add_rule (rule); + ctxt.add_rule (rule); bool warned; if (m_var_decl) - warned = warning_meta (rich_loc, m, get_controlling_option (), - "%qE on a pointer to automatic variable %qE", - m_fndecl, m_var_decl); + warned = ctxt.warn ("%qE on a pointer to automatic variable %qE", + m_fndecl, m_var_decl); else - warned = warning_meta (rich_loc, m, get_controlling_option (), - "%qE on a pointer to an on-stack buffer", - m_fndecl); + warned = ctxt.warn ("%qE on a pointer to an on-stack buffer", + m_fndecl); if (warned) { if (m_var_decl) inform (DECL_SOURCE_LOCATION (m_var_decl), "%qE declared on stack here", m_var_decl); - inform (rich_loc->get_loc (), "perhaps use %qs rather than %qE", + inform (ctxt.get_location (), "perhaps use %qs rather than %qE", "setenv", m_fndecl); } @@ -1733,18 +1730,15 @@ public: return OPT_Wanalyzer_undefined_behavior_strtok; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* CWE-476: NULL Pointer Dereference. */ - diagnostic_metadata m; - m.add_cwe (476); - if (warning_meta - (rich_loc, m, get_controlling_option (), - "calling %qD for first time with NULL as argument 1" - " has undefined behavior", - get_callee_fndecl ())) + ctxt.add_cwe (476); + if (ctxt.warn ("calling %qD for first time with NULL as argument 1" + " has undefined behavior", + get_callee_fndecl ())) { - inform (rich_loc->get_loc (), + inform (ctxt.get_location (), "some implementations of %qD may crash on such input", get_callee_fndecl ()); return true; diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index c7d337033f1e..48d9be9ba2dc 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -109,6 +109,51 @@ evdesc::event_desc::formatted_print (const char *fmt, ...) const return result; } +/* class diagnostic_emission_context. */ + +/* Get the pending_diagnostic being emitted. */ + +const pending_diagnostic & +diagnostic_emission_context::get_pending_diagnostic () const +{ + return *m_sd.m_d.get (); +} + +/* Emit a warning, using the rich_location, metadata, and the + pending_diagnostic's option. */ + +bool +diagnostic_emission_context::warn (const char *gmsgid, ...) +{ + const pending_diagnostic &pd = get_pending_diagnostic (); + auto_diagnostic_group d; + va_list ap; + va_start (ap, gmsgid); + const bool result = emit_diagnostic_valist (DK_WARNING, + &m_rich_loc, &m_metadata, + pd.get_controlling_option (), + gmsgid, &ap); + va_end (ap); + return result; +} + +/* Emit a note, using the rich_location and metadata (and the + pending_diagnostic's option). */ + +void +diagnostic_emission_context::inform (const char *gmsgid, ...) +{ + const pending_diagnostic &pd = get_pending_diagnostic (); + auto_diagnostic_group d; + va_list ap; + va_start (ap, gmsgid); + emit_diagnostic_valist (DK_NOTE, + &m_rich_loc, &m_metadata, + pd.get_controlling_option (), + gmsgid, &ap); + va_end (ap); +} + /* Return true if T1 and T2 are "the same" for the purposes of diagnostic deduplication. */ diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h index 7582b37efe79..e393f9ae24ed 100644 --- a/gcc/analyzer/pending-diagnostic.h +++ b/gcc/analyzer/pending-diagnostic.h @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H +#include "diagnostic-metadata.h" #include "diagnostic-path.h" #include "analyzer/sm.h" @@ -144,6 +145,47 @@ struct final_event : public event_desc } /* end of namespace evdesc */ +/* A bundle of information for use by implementations of the + pending_diagnostic::emit vfunc. + + The rich_location will have already been populated with a + diagnostic_path. */ + +class diagnostic_emission_context +{ +public: + diagnostic_emission_context (const saved_diagnostic &sd, + rich_location &rich_loc, + diagnostic_metadata &metadata, + logger *logger) + : m_sd (sd), + m_rich_loc (rich_loc), + m_metadata (metadata), + m_logger (logger) + { + } + + const pending_diagnostic &get_pending_diagnostic () const; + + bool warn (const char *, ...) ATTRIBUTE_GCC_DIAG (2,3); + void inform (const char *, ...) ATTRIBUTE_GCC_DIAG (2,3); + + location_t get_location () const { return m_rich_loc.get_loc (); } + logger *get_logger () const { return m_logger; } + + void add_cwe (int cwe) { m_metadata.add_cwe (cwe); } + void add_rule (const diagnostic_metadata::rule &r) + { + m_metadata.add_rule (r); + } + +private: + const saved_diagnostic &m_sd; + rich_location &m_rich_loc; + diagnostic_metadata &m_metadata; + logger *m_logger; +}; + /* An abstract base class for capturing information about a diagnostic in a form that is ready to emit at a later point (or be rejected). Each kind of diagnostic will have a concrete subclass of @@ -177,10 +219,9 @@ class pending_diagnostic path being explored. By default, don't terminate the path. */ virtual bool terminate_path_p () const { return false; } - /* Vfunc for emitting the diagnostic. The rich_location will have been - populated with a diagnostic_path. + /* Vfunc for emitting the diagnostic. Return true if a diagnostic is actually emitted. */ - virtual bool emit (rich_location *, logger *) = 0; + virtual bool emit (diagnostic_emission_context &) = 0; /* Hand-coded RTTI: get an ID for the subclass. */ virtual const char *get_kind () const = 0; @@ -361,6 +402,15 @@ class pending_diagnostic /* Default implementation: accept this path. */ return true; } + + /* Vfunc for use in SARIF output to give pending_diagnostic subclasses + the opportunity to add diagnostic-specific properties to the SARIF + "result" object for the diagnostic. + This is intended for use when debugging a diagnostic. */ + virtual void maybe_add_sarif_properties (sarif_object &/*result_obj*/) const + { + /* Default no-op implementation. */ + } }; /* A template to make it easier to make subclasses of pending_diagnostic. diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 420c10380a4e..2157ad2578b8 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -40,7 +40,6 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "tree-pretty-print.h" #include "diagnostic-color.h" -#include "diagnostic-metadata.h" #include "bitmap.h" #include "selftest.h" #include "analyzer/analyzer.h" @@ -79,6 +78,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/checker-path.h" #include "analyzer/feasible-graph.h" #include "analyzer/record-layout.h" +#include "diagnostic-format-sarif.h" #if ENABLE_ANALYZER @@ -512,7 +512,7 @@ public: bool terminate_path_p () const final override { return true; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { switch (m_pkind) { @@ -520,37 +520,30 @@ public: gcc_unreachable (); case POISON_KIND_UNINIT: { - diagnostic_metadata m; - m.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */ - return warning_meta (rich_loc, m, get_controlling_option (), - "use of uninitialized value %qE", - m_expr); + ctxt.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */ + return ctxt.warn ("use of uninitialized value %qE", + m_expr); } break; case POISON_KIND_FREED: { - diagnostic_metadata m; - m.add_cwe (416); /* "CWE-416: Use After Free". */ - return warning_meta (rich_loc, m, get_controlling_option (), - "use after % of %qE", - m_expr); + ctxt.add_cwe (416); /* "CWE-416: Use After Free". */ + return ctxt.warn ("use after % of %qE", + m_expr); } break; case POISON_KIND_DELETED: { - diagnostic_metadata m; - m.add_cwe (416); /* "CWE-416: Use After Free". */ - return warning_meta (rich_loc, m, get_controlling_option (), - "use after % of %qE", - m_expr); + ctxt.add_cwe (416); /* "CWE-416: Use After Free". */ + return ctxt.warn ("use after % of %qE", + m_expr); } break; case POISON_KIND_POPPED_STACK: { /* TODO: which CWE? */ - return warning_at - (rich_loc, get_controlling_option (), - "dereferencing pointer %qE to within stale stack frame", + return ctxt.warn + ("dereferencing pointer %qE to within stale stack frame", m_expr); } break; @@ -655,10 +648,9 @@ public: return OPT_Wanalyzer_shift_count_negative; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at (rich_loc, get_controlling_option (), - "shift by negative count (%qE)", m_count_cst); + return ctxt.warn ("shift by negative count (%qE)", m_count_cst); } label_text describe_final_event (const evdesc::final_event &ev) final override @@ -702,11 +694,10 @@ public: return OPT_Wanalyzer_shift_count_overflow; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at (rich_loc, get_controlling_option (), - "shift by count (%qE) >= precision of type (%qi)", - m_count_cst, m_operand_precision); + return ctxt.warn ("shift by count (%qE) >= precision of type (%qi)", + m_count_cst, m_operand_precision); } label_text describe_final_event (const evdesc::final_event &ev) final override @@ -2840,23 +2831,20 @@ public: return OPT_Wanalyzer_write_to_const; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; bool warned; switch (m_reg->get_kind ()) { default: - warned = warning_at (rich_loc, get_controlling_option (), - "write to % object %qE", m_decl); + warned = ctxt.warn ("write to % object %qE", m_decl); break; case RK_FUNCTION: - warned = warning_at (rich_loc, get_controlling_option (), - "write to function %qE", m_decl); + warned = ctxt.warn ("write to function %qE", m_decl); break; case RK_LABEL: - warned = warning_at (rich_loc, get_controlling_option (), - "write to label %qE", m_decl); + warned = ctxt.warn ("write to label %qE", m_decl); break; } if (warned) @@ -2908,10 +2896,9 @@ public: return OPT_Wanalyzer_write_to_string_literal; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at (rich_loc, get_controlling_option (), - "write to string literal"); + return ctxt.warn ("write to string literal"); /* Ideally we would show the location of the STRING_CST as well, but it is not available at this point. */ } @@ -3112,14 +3099,12 @@ public: return OPT_Wanalyzer_allocation_size; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; - m.add_cwe (131); + ctxt.add_cwe (131); - return warning_meta (rich_loc, m, get_controlling_option (), - "allocated buffer size is not a multiple" - " of the pointee's size"); + return ctxt.warn ("allocated buffer size is not a multiple" + " of the pointee's size"); } label_text describe_final_event (const evdesc::final_event &ev) final @@ -5970,15 +5955,14 @@ public: return same_tree_p (m_arg, ((const float_as_size_arg &) other).m_arg); } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; - bool warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of floating-point arithmetic here might" - " yield unexpected results"); + bool warned = ctxt.warn ("use of floating-point arithmetic here might" + " yield unexpected results"); if (warned) - inform (rich_loc->get_loc (), "only use operands of an integer type" - " inside the size argument"); + inform (ctxt.get_location (), + "only use operands of an integer type" + " inside the size argument"); return warned; } @@ -6214,37 +6198,33 @@ public: return OPT_Wanalyzer_exposure_through_uninit_copy; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-200: Exposure of Sensitive Information to an Unauthorized Actor. */ - m.add_cwe (200); + ctxt.add_cwe (200); enum memory_space mem_space = get_src_memory_space (); bool warned; switch (mem_space) { default: - warned = warning_meta - (rich_loc, m, get_controlling_option (), - "potential exposure of sensitive information" - " by copying uninitialized data across trust boundary"); + warned = ctxt.warn ("potential exposure of sensitive information" + " by copying uninitialized data" + " across trust boundary"); break; case MEMSPACE_STACK: - warned = warning_meta - (rich_loc, m, get_controlling_option (), - "potential exposure of sensitive information" - " by copying uninitialized data from stack across trust boundary"); + warned = ctxt.warn ("potential exposure of sensitive information" + " by copying uninitialized data from stack" + " across trust boundary"); break; case MEMSPACE_HEAP: - warned = warning_meta - (rich_loc, m, get_controlling_option (), - "potential exposure of sensitive information" - " by copying uninitialized data from heap across trust boundary"); + warned = ctxt.warn ("potential exposure of sensitive information" + " by copying uninitialized data from heap" + " across trust boundary"); break; } if (warned) { - location_t loc = rich_loc->get_loc (); + const location_t loc = ctxt.get_location (); inform_number_of_uninit_bits (loc); complain_about_uninit_ranges (loc); @@ -6276,6 +6256,17 @@ public: interest->add_region_creation (m_src_region); } + void + maybe_add_sarif_properties (sarif_object &result_obj) const final override + { + sarif_property_bag &props = result_obj.get_or_create_properties (); +#define PROPERTY_PREFIX "gcc/-Wanalyzer-exposure-through-uninit-copy/" + props.set (PROPERTY_PREFIX "src_region", m_src_region->to_json ()); + props.set (PROPERTY_PREFIX "dest_region", m_dest_region->to_json ()); + props.set (PROPERTY_PREFIX "copied_sval", m_copied_sval->to_json ()); +#undef PROPERTY_PREFIX + } + private: enum memory_space get_src_memory_space () const { diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 4feb9721ae78..9b27e8febcc9 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -40,7 +40,6 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "tree-pretty-print.h" #include "diagnostic-color.h" -#include "diagnostic-metadata.h" #include "bitmap.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc index 34bbd84f6e7e..7f8a1d9b949a 100644 --- a/gcc/analyzer/sm-fd.cc +++ b/gcc/analyzer/sm-fd.cc @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "options.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -465,19 +464,16 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { /*CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime */ - diagnostic_metadata m; - m.add_cwe (775); + ctxt.add_cwe (775); if (m_arg) - return warning_meta (rich_loc, m, get_controlling_option (), - "leak of file descriptor %qE", m_arg); + return ctxt.warn ("leak of file descriptor %qE", m_arg); else - return warning_meta (rich_loc, m, get_controlling_option (), - "leak of file descriptor"); + return ctxt.warn ("leak of file descriptor"); } label_text @@ -550,20 +546,18 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { bool warned; switch (m_fd_dir) { case DIRS_READ: - warned = warning_at (rich_loc, get_controlling_option (), - "%qE on read-only file descriptor %qE", - m_callee_fndecl, m_arg); + warned = ctxt.warn ("%qE on read-only file descriptor %qE", + m_callee_fndecl, m_arg); break; case DIRS_WRITE: - warned = warning_at (rich_loc, get_controlling_option (), - "%qE on write-only file descriptor %qE", - m_callee_fndecl, m_arg); + warned = ctxt.warn ("%qE on write-only file descriptor %qE", + m_callee_fndecl, m_arg); break; default: gcc_unreachable (); @@ -612,13 +606,11 @@ public: return OPT_Wanalyzer_fd_double_close; } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; // CWE-1341: Multiple Releases of Same Resource or Handle - m.add_cwe (1341); - return warning_meta (rich_loc, m, get_controlling_option (), - "double % of file descriptor %qE", m_arg); + ctxt.add_cwe (1341); + return ctxt.warn ("double % of file descriptor %qE", m_arg); } label_text @@ -677,12 +669,10 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { - bool warned; - warned = warning_at (rich_loc, get_controlling_option (), - "%qE on closed file descriptor %qE", m_callee_fndecl, - m_arg); + bool warned = ctxt.warn ("%qE on closed file descriptor %qE", + m_callee_fndecl, m_arg); if (warned) inform_filedescriptor_attribute (DIRS_READ_WRITE); return warned; @@ -748,12 +738,10 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { - bool warned; - warned = warning_at (rich_loc, get_controlling_option (), - "%qE on possibly invalid file descriptor %qE", - m_callee_fndecl, m_arg); + bool warned = ctxt.warn ("%qE on possibly invalid file descriptor %qE", + m_callee_fndecl, m_arg); if (warned) inform_filedescriptor_attribute (DIRS_READ_WRITE); return warned; @@ -859,14 +847,12 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { /* CWE-666: Operation on Resource in Wrong Phase of Lifetime. */ - diagnostic_metadata m; - m.add_cwe (666); - return warning_at (rich_loc, get_controlling_option (), - "%qE on file descriptor %qE in wrong phase", - m_callee_fndecl, m_arg); + ctxt.add_cwe (666); + return ctxt.warn ("%qE on file descriptor %qE in wrong phase", + m_callee_fndecl, m_arg); } label_text @@ -1019,25 +1005,22 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { switch (m_expected_type) { default: gcc_unreachable (); case EXPECTED_TYPE_SOCKET: - return warning_at (rich_loc, get_controlling_option (), - "%qE on non-socket file descriptor %qE", - m_callee_fndecl, m_arg); + return ctxt.warn ("%qE on non-socket file descriptor %qE", + m_callee_fndecl, m_arg); case EXPECTED_TYPE_STREAM_SOCKET: if (m_sm.is_datagram_socket_fd_p (m_actual_state)) - return warning_at (rich_loc, get_controlling_option (), - "%qE on datagram socket file descriptor %qE", - m_callee_fndecl, m_arg); + return ctxt.warn ("%qE on datagram socket file descriptor %qE", + m_callee_fndecl, m_arg); else - return warning_at (rich_loc, get_controlling_option (), - "%qE on non-stream-socket file descriptor %qE", - m_callee_fndecl, m_arg); + return ctxt.warn ("%qE on non-stream-socket file descriptor %qE", + m_callee_fndecl, m_arg); } } diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 0252b3922d42..f8e31f873a5a 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "options.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -176,14 +175,12 @@ public: return OPT_Wanalyzer_double_fclose; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-1341: Multiple Releases of Same Resource or Handle. */ - m.add_cwe (1341); - return warning_meta (rich_loc, m, get_controlling_option (), - "double % of FILE %qE", - m_arg); + ctxt.add_cwe (1341); + return ctxt.warn ("double % of FILE %qE", + m_arg); } label_text describe_state_change (const evdesc::state_change &change) @@ -224,19 +221,15 @@ public: return OPT_Wanalyzer_file_leak; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-775: "Missing Release of File Descriptor or Handle after Effective Lifetime". */ - m.add_cwe (775); + ctxt.add_cwe (775); if (m_arg) - return warning_meta (rich_loc, m, get_controlling_option (), - "leak of FILE %qE", - m_arg); + return ctxt.warn ("leak of FILE %qE", m_arg); else - return warning_meta (rich_loc, m, get_controlling_option (), - "leak of FILE"); + return ctxt.warn ("leak of FILE"); } label_text describe_state_change (const evdesc::state_change &change) diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index 5af654414b49..bb7844483979 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "bitmap.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -840,23 +839,20 @@ public: return OPT_Wanalyzer_mismatching_deallocation; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; - diagnostic_metadata m; - m.add_cwe (762); /* CWE-762: Mismatched Memory Management Routines. */ + ctxt.add_cwe (762); /* CWE-762: Mismatched Memory Management Routines. */ if (const deallocator *expected_dealloc = m_expected_deallocators->maybe_get_single ()) - return warning_meta (rich_loc, m, get_controlling_option (), - "%qE should have been deallocated with %qs" - " but was deallocated with %qs", - m_arg, expected_dealloc->m_name, - m_actual_dealloc->m_name); + return ctxt.warn ("%qE should have been deallocated with %qs" + " but was deallocated with %qs", + m_arg, expected_dealloc->m_name, + m_actual_dealloc->m_name); else - return warning_meta (rich_loc, m, get_controlling_option (), - "%qs called on %qE returned from a mismatched" - " allocation function", - m_actual_dealloc->m_name, m_arg); + return ctxt.warn ("%qs called on %qE returned from a mismatched" + " allocation function", + m_actual_dealloc->m_name, m_arg); } label_text describe_state_change (const evdesc::state_change &change) @@ -919,13 +915,11 @@ public: return OPT_Wanalyzer_double_free; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; - diagnostic_metadata m; - m.add_cwe (415); /* CWE-415: Double Free. */ - return warning_meta (rich_loc, m, get_controlling_option (), - "double-%qs of %qE", m_funcname, m_arg); + ctxt.add_cwe (415); /* CWE-415: Double Free. */ + return ctxt.warn ("double-%qs of %qE", m_funcname, m_arg); } label_text describe_state_change (const evdesc::state_change &change) @@ -1015,13 +1009,11 @@ public: return OPT_Wanalyzer_possible_null_dereference; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */ - diagnostic_metadata m; - m.add_cwe (690); - return warning_meta (rich_loc, m, get_controlling_option (), - "dereference of possibly-NULL %qE", m_arg); + ctxt.add_cwe (690); + return ctxt.warn ("dereference of possibly-NULL %qE", m_arg); } label_text describe_final_event (const evdesc::final_event &ev) final override @@ -1104,16 +1096,14 @@ public: return OPT_Wanalyzer_possible_null_argument; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */ auto_diagnostic_group d; - diagnostic_metadata m; - m.add_cwe (690); + ctxt.add_cwe (690); bool warned - = warning_meta (rich_loc, m, get_controlling_option (), - "use of possibly-NULL %qE where non-null expected", - m_arg); + = ctxt.warn ("use of possibly-NULL %qE where non-null expected", + m_arg); if (warned) inform_nonnull_attribute (m_fndecl, m_arg_idx); return warned; @@ -1157,13 +1147,11 @@ public: bool terminate_path_p () const final override { return true; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* CWE-476: NULL Pointer Dereference. */ - diagnostic_metadata m; - m.add_cwe (476); - return warning_meta (rich_loc, m, get_controlling_option (), - "dereference of NULL %qE", m_arg); + ctxt.add_cwe (476); + return ctxt.warn ("dereference of NULL %qE", m_arg); } label_text describe_return_of_state (const evdesc::return_of_state &info) @@ -1227,21 +1215,18 @@ public: bool terminate_path_p () const final override { return true; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* CWE-476: NULL Pointer Dereference. */ auto_diagnostic_group d; - diagnostic_metadata m; - m.add_cwe (476); + ctxt.add_cwe (476); bool warned; if (zerop (m_arg)) - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of NULL where non-null expected"); + warned = ctxt.warn ("use of NULL where non-null expected"); else - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of NULL %qE where non-null expected", - m_arg); + warned = ctxt.warn ("use of NULL %qE where non-null expected", + m_arg); if (warned) inform_nonnull_attribute (m_fndecl, m_arg_idx); return warned; @@ -1284,14 +1269,12 @@ public: return OPT_Wanalyzer_use_after_free; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* CWE-416: Use After Free. */ - diagnostic_metadata m; - m.add_cwe (416); - return warning_meta (rich_loc, m, get_controlling_option (), - "use after %<%s%> of %qE", - m_deallocator->m_name, m_arg); + ctxt.add_cwe (416); + return ctxt.warn ("use after %<%s%> of %qE", + m_deallocator->m_name, m_arg); } label_text describe_state_change (const evdesc::state_change &change) @@ -1378,17 +1361,14 @@ public: return OPT_Wanalyzer_malloc_leak; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* "CWE-401: Missing Release of Memory after Effective Lifetime". */ - diagnostic_metadata m; - m.add_cwe (401); + ctxt.add_cwe (401); if (m_arg) - return warning_meta (rich_loc, m, get_controlling_option (), - "leak of %qE", m_arg); + return ctxt.warn ("leak of %qE", m_arg); else - return warning_meta (rich_loc, m, get_controlling_option (), - "leak of %qs", ""); + return ctxt.warn ("leak of %qs", ""); } label_text describe_state_change (const evdesc::state_change &change) @@ -1452,11 +1432,10 @@ public: return OPT_Wanalyzer_free_of_non_heap; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; - diagnostic_metadata m; - m.add_cwe (590); /* CWE-590: Free of Memory not on the Heap. */ + ctxt.add_cwe (590); /* CWE-590: Free of Memory not on the Heap. */ switch (get_memory_space ()) { default: @@ -1466,16 +1445,14 @@ public: case MEMSPACE_CODE: case MEMSPACE_GLOBALS: case MEMSPACE_READONLY_DATA: - return warning_meta (rich_loc, m, get_controlling_option (), - "%<%s%> of %qE which points to memory" - " not on the heap", - m_funcname, m_arg); + return ctxt.warn ("%<%s%> of %qE which points to memory" + " not on the heap", + m_funcname, m_arg); break; case MEMSPACE_STACK: - return warning_meta (rich_loc, m, get_controlling_option (), - "%<%s%> of %qE which points to memory" - " on the stack", - m_funcname, m_arg); + return ctxt.warn ("%<%s%> of %qE which points to memory" + " on the stack", + m_funcname, m_arg); break; } } @@ -1531,7 +1508,7 @@ public: return OPT_Wanalyzer_deref_before_check; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { /* Don't emit the warning if we can't show where the deref and the check occur. */ @@ -1605,10 +1582,9 @@ public: m_deref_enode->get_supernode ()->m_bb)) return false; - return warning_at (rich_loc, get_controlling_option (), - "check of %qE for NULL after already" - " dereferencing it", - m_arg); + return ctxt.warn ("check of %qE for NULL after already" + " dereferencing it", + m_arg); } label_text describe_state_change (const evdesc::state_change &change) diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc index 4c88bcaeb2b3..cd594e09c005 100644 --- a/gcc/analyzer/sm-pattern-test.cc +++ b/gcc/analyzer/sm-pattern-test.cc @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "tree-pretty-print.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -92,11 +91,10 @@ public: return 0; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at (rich_loc, get_controlling_option (), - "pattern match on %<%E %s %E%>", - m_lhs, op_symbol_code (m_op), m_rhs); + return ctxt.warn ("pattern match on %<%E %s %E%>", + m_lhs, op_symbol_code (m_op), m_rhs); } private: diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc index 0597e390b3bb..4776d6465bb5 100644 --- a/gcc/analyzer/sm-sensitive.cc +++ b/gcc/analyzer/sm-sensitive.cc @@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "options.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -95,15 +94,12 @@ public: return OPT_Wanalyzer_exposure_through_output_file; } - bool emit (rich_location *rich_loc, - logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-532: Information Exposure Through Log Files */ - m.add_cwe (532); - return warning_meta (rich_loc, m, get_controlling_option (), - "sensitive value %qE written to output file", - m_arg); + ctxt.add_cwe (532); + return ctxt.warn ("sensitive value %qE written to output file", + m_arg); } label_text describe_state_change (const evdesc::state_change &change) diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 9ebcbdbc8e01..6bca395ac5c7 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "bitmap.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -114,15 +113,13 @@ public: return OPT_Wanalyzer_unsafe_call_within_signal_handler; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { auto_diagnostic_group d; - diagnostic_metadata m; /* CWE-479: Signal Handler Use of a Non-reentrant Function. */ - m.add_cwe (479); - if (warning_meta (rich_loc, m, get_controlling_option (), - "call to %qD from within signal handler", - m_unsafe_fndecl)) + ctxt.add_cwe (479); + if (ctxt.warn ("call to %qD from within signal handler", + m_unsafe_fndecl)) { /* If we know a possible alternative function, add a note suggesting the replacement. */ diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index dfd5f7fa5d2c..d01e3f03951d 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "options.h" #include "diagnostic-path.h" -#include "diagnostic-metadata.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "gimple-iterator.h" @@ -211,33 +210,29 @@ public: return OPT_Wanalyzer_tainted_array_index; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-129: "Improper Validation of Array Index". */ - m.add_cwe (129); + ctxt.add_cwe (129); if (m_arg) switch (m_has_bounds) { default: gcc_unreachable (); case BOUNDS_NONE: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE" - " in array lookup without bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE" + " in array lookup without bounds checking", + m_arg); break; case BOUNDS_UPPER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE" - " in array lookup without checking for negative", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE" + " in array lookup without checking for negative", + m_arg); break; case BOUNDS_LOWER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE" - " in array lookup without upper-bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE" + " in array lookup without upper-bounds checking", + m_arg); break; } else @@ -246,21 +241,18 @@ public: default: gcc_unreachable (); case BOUNDS_NONE: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value" - " in array lookup without bounds checking"); + return ctxt.warn ("use of attacker-controlled value" + " in array lookup without bounds checking"); break; case BOUNDS_UPPER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value" - " in array lookup without checking for" - " negative"); + return ctxt.warn ("use of attacker-controlled value" + " in array lookup without checking for" + " negative"); break; case BOUNDS_LOWER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value" - " in array lookup without upper-bounds" - " checking"); + return ctxt.warn ("use of attacker-controlled value" + " in array lookup without upper-bounds" + " checking"); break; } } @@ -327,33 +319,29 @@ public: return OPT_Wanalyzer_tainted_offset; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-823: "Use of Out-of-range Pointer Offset". */ - m.add_cwe (823); + ctxt.add_cwe (823); if (m_arg) switch (m_has_bounds) { default: gcc_unreachable (); case BOUNDS_NONE: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as offset" - " without bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as offset" + " without bounds checking", + m_arg); break; case BOUNDS_UPPER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as offset" - " without lower-bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as offset" + " without lower-bounds checking", + m_arg); break; case BOUNDS_LOWER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as offset" - " without upper-bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as offset" + " without upper-bounds checking", + m_arg); break; } else @@ -362,19 +350,16 @@ public: default: gcc_unreachable (); case BOUNDS_NONE: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as offset" - " without bounds checking"); + return ctxt.warn ("use of attacker-controlled value as offset" + " without bounds checking"); break; case BOUNDS_UPPER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as offset" - " without lower-bounds checking"); + return ctxt.warn ("use of attacker-controlled value as offset" + " without lower-bounds checking"); break; case BOUNDS_LOWER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as offset" - " without upper-bounds checking"); + return ctxt.warn ("use of attacker-controlled value as offset" + " without upper-bounds checking"); break; } } @@ -437,33 +422,29 @@ public: return OPT_Wanalyzer_tainted_size; } - bool emit (rich_location *rich_loc, logger *) override + bool emit (diagnostic_emission_context &ctxt) override { /* "CWE-129: Improper Validation of Array Index". */ - diagnostic_metadata m; - m.add_cwe (129); + ctxt.add_cwe (129); if (m_arg) switch (m_has_bounds) { default: gcc_unreachable (); case BOUNDS_NONE: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as size" - " without bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as size" + " without bounds checking", + m_arg); break; case BOUNDS_UPPER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as size" - " without lower-bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as size" + " without lower-bounds checking", + m_arg); break; case BOUNDS_LOWER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as size" - " without upper-bounds checking", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as size" + " without upper-bounds checking", + m_arg); break; } else @@ -472,19 +453,16 @@ public: default: gcc_unreachable (); case BOUNDS_NONE: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as size" - " without bounds checking"); + return ctxt.warn ("use of attacker-controlled value as size" + " without bounds checking"); break; case BOUNDS_UPPER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as size" - " without lower-bounds checking"); + return ctxt.warn ("use of attacker-controlled value as size" + " without lower-bounds checking"); break; case BOUNDS_LOWER: - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as size" - " without upper-bounds checking"); + return ctxt.warn ("use of attacker-controlled value as size" + " without upper-bounds checking"); break; } } @@ -547,9 +525,9 @@ public: return "tainted_access_attrib_size"; } - bool emit (rich_location *rich_loc, logger *logger) final override + bool emit (diagnostic_emission_context &ctxt) final override { - bool warned = tainted_size::emit (rich_loc, logger); + bool warned = tainted_size::emit (ctxt); if (warned) { inform (DECL_SOURCE_LOCATION (m_callee_fndecl), @@ -583,20 +561,17 @@ public: return OPT_Wanalyzer_tainted_divisor; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* CWE-369: "Divide By Zero". */ - m.add_cwe (369); + ctxt.add_cwe (369); if (m_arg) - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as divisor" - " without checking for zero", - m_arg); + return ctxt.warn ("use of attacker-controlled value %qE as divisor" + " without checking for zero", + m_arg); else - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as divisor" - " without checking for zero"); + return ctxt.warn ("use of attacker-controlled value as divisor" + " without checking for zero"); } label_text describe_final_event (const evdesc::final_event &ev) final override @@ -645,11 +620,10 @@ public: return OPT_Wanalyzer_tainted_allocation_size; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* "CWE-789: Memory Allocation with Excessive Size Value". */ - m.add_cwe (789); + ctxt.add_cwe (789); bool warned; if (m_arg) @@ -658,24 +632,21 @@ public: default: gcc_unreachable (); case BOUNDS_NONE: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as" - " allocation size without bounds checking", - m_arg); + warned = ctxt.warn ("use of attacker-controlled value %qE as" + " allocation size without bounds checking", + m_arg); break; case BOUNDS_UPPER: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as" - " allocation size without" - " lower-bounds checking", - m_arg); + warned = ctxt.warn ("use of attacker-controlled value %qE as" + " allocation size without" + " lower-bounds checking", + m_arg); break; case BOUNDS_LOWER: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value %qE as" - " allocation size without" - " upper-bounds checking", - m_arg); + warned = ctxt.warn ("use of attacker-controlled value %qE as" + " allocation size without" + " upper-bounds checking", + m_arg); break; } else @@ -684,27 +655,24 @@ public: default: gcc_unreachable (); case BOUNDS_NONE: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as" - " allocation size without bounds" - " checking"); + warned = ctxt.warn ("use of attacker-controlled value as" + " allocation size without bounds" + " checking"); break; case BOUNDS_UPPER: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as" - " allocation size without" - " lower-bounds checking"); + warned = ctxt.warn ("use of attacker-controlled value as" + " allocation size without" + " lower-bounds checking"); break; case BOUNDS_LOWER: - warned = warning_meta (rich_loc, m, get_controlling_option (), - "use of attacker-controlled value as" - " allocation size without" - " upper-bounds checking"); + warned = ctxt.warn ("use of attacker-controlled value as" + " allocation size without" + " upper-bounds checking"); break; } if (warned) { - location_t loc = rich_loc->get_loc (); + const location_t loc = ctxt.get_location (); switch (m_mem_space) { default: @@ -800,15 +768,13 @@ public: return OPT_Wanalyzer_tainted_assertion; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; /* "CWE-617: Reachable Assertion". */ - m.add_cwe (617); + ctxt.add_cwe (617); - return warning_meta (rich_loc, m, get_controlling_option (), - "use of attacked-controlled value in" - " condition for assertion"); + return ctxt.warn ("use of attacked-controlled value in" + " condition for assertion"); } location_t fixup_location (location_t loc, diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 602508598cc9..be1802e1e5a8 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -38,7 +38,6 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "tree-pretty-print.h" #include "diagnostic-color.h" -#include "diagnostic-metadata.h" #include "bitmap.h" #include "selftest.h" #include "analyzer/analyzer.h" diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc index f79b2a7d7b51..7cdfb203a339 100644 --- a/gcc/analyzer/varargs.cc +++ b/gcc/analyzer/varargs.cc @@ -41,7 +41,6 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/supergraph.h" #include "analyzer/diagnostic-manager.h" #include "analyzer/exploded-graph.h" -#include "diagnostic-metadata.h" #include "analyzer/call-details.h" #if ENABLE_ANALYZER @@ -403,11 +402,9 @@ public: && 0 == strcmp (m_usage_fnname, other.m_usage_fnname)); } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - auto_diagnostic_group d; - return warning_at (rich_loc, get_controlling_option (), - "%qs after %qs", m_usage_fnname, "va_end"); + return ctxt.warn ("%qs after %qs", m_usage_fnname, "va_end"); } const char *get_kind () const final override @@ -478,11 +475,9 @@ public: return va_list_sm_diagnostic::subclass_equal_p (other); } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - auto_diagnostic_group d; - return warning_at (rich_loc, get_controlling_option (), - "missing call to %qs", "va_end"); + return ctxt.warn ("missing call to %qs", "va_end"); } const char *get_kind () const final override { return "va_list_leak"; } @@ -892,18 +887,15 @@ public: return OPT_Wanalyzer_va_arg_type_mismatch; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - auto_diagnostic_group d; - diagnostic_metadata m; /* "CWE-686: Function Call With Incorrect Argument Type". */ - m.add_cwe (686); + ctxt.add_cwe (686); bool warned - = warning_meta (rich_loc, m, get_controlling_option (), - "% expected %qT but received %qT" - " for variadic argument %i of %qE", - m_expected_type, m_actual_type, - get_variadic_index_for_diagnostic (), m_va_list_tree); + = ctxt.warn ("% expected %qT but received %qT" + " for variadic argument %i of %qE", + m_expected_type, m_actual_type, + get_variadic_index_for_diagnostic (), m_va_list_tree); return warned; } @@ -942,15 +934,12 @@ public: return OPT_Wanalyzer_va_list_exhausted; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - auto_diagnostic_group d; - diagnostic_metadata m; /* CWE-685: Function Call With Incorrect Number of Arguments. */ - m.add_cwe (685); - bool warned = warning_meta (rich_loc, m, get_controlling_option (), - "%qE has no more arguments (%i consumed)", - m_va_list_tree, get_num_consumed ()); + ctxt.add_cwe (685); + bool warned = ctxt.warn ("%qE has no more arguments (%i consumed)", + m_va_list_tree, get_num_consumed ()); return warned; } diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h index 04eba3d140e6..965c9e986ab6 100644 --- a/gcc/diagnostic-core.h +++ b/gcc/diagnostic-core.h @@ -123,6 +123,12 @@ extern bool emit_diagnostic (diagnostic_t, rich_location *, int, const char *, ...) ATTRIBUTE_GCC_DIAG(4,5); extern bool emit_diagnostic_valist (diagnostic_t, location_t, int, const char *, va_list *) ATTRIBUTE_GCC_DIAG (4,0); +extern bool emit_diagnostic_valist (diagnostic_t, + rich_location *, + const diagnostic_metadata *, + int, + const char *, + va_list *) ATTRIBUTE_GCC_DIAG (5,0); extern bool seen_error (void); #ifdef BUFSIZ diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index 1bb728654e6c..67775929f855 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -569,16 +569,20 @@ sarif_builder::make_result_object (diagnostic_context *context, free (rule_id); } - /* "taxa" property (SARIF v2.1.0 section 3.27.8). */ if (diagnostic->metadata) - if (int cwe_id = diagnostic->metadata->get_cwe ()) - { - json::array *taxa_arr = new json::array (); - json::object *cwe_id_obj - = make_reporting_descriptor_reference_object_for_cwe_id (cwe_id); - taxa_arr->append (cwe_id_obj); - result_obj->set ("taxa", taxa_arr); - } + { + /* "taxa" property (SARIF v2.1.0 section 3.27.8). */ + if (int cwe_id = diagnostic->metadata->get_cwe ()) + { + json::array *taxa_arr = new json::array (); + json::object *cwe_id_obj + = make_reporting_descriptor_reference_object_for_cwe_id (cwe_id); + taxa_arr->append (cwe_id_obj); + result_obj->set ("taxa", taxa_arr); + } + + diagnostic->metadata->maybe_add_sarif_properties (*result_obj); + } /* "level" property (SARIF v2.1.0 section 3.27.10). */ if (const char *sarif_level = maybe_get_sarif_level (diagnostic->kind)) diff --git a/gcc/diagnostic-metadata.h b/gcc/diagnostic-metadata.h index 8e06c89d74a4..1af80fd9be77 100644 --- a/gcc/diagnostic-metadata.h +++ b/gcc/diagnostic-metadata.h @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DIAGNOSTIC_METADATA_H #define GCC_DIAGNOSTIC_METADATA_H +class sarif_object; + /* A bundle of additional metadata that can be associated with a diagnostic. @@ -63,6 +65,14 @@ class diagnostic_metadata }; diagnostic_metadata () : m_cwe (0) {} + virtual ~diagnostic_metadata () {} + + /* Hook for SARIF output to allow for adding diagnostic-specific + properties to the result object's property bag. */ + virtual void + maybe_add_sarif_properties (sarif_object &/*result_obj*/) const + { + } void add_cwe (int cwe) { m_cwe = cwe; } int get_cwe () const { return m_cwe; } diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index 4f66fa6acaa8..2e3d37b04ccc 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -1834,6 +1834,18 @@ emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt, return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind); } +/* As above, but with rich_location and metadata. */ + +bool +emit_diagnostic_valist (diagnostic_t kind, + rich_location *richloc, + const diagnostic_metadata *metadata, + int opt, + const char *gmsgid, va_list *ap) +{ + return diagnostic_impl (richloc, metadata, opt, gmsgid, ap, kind); +} + /* An informative note at LOCATION. Use this for additional details on an error message. */ void diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-accept.c b/gcc/testsuite/gcc.dg/analyzer/fd-accept.c index cce95555421b..d07ab154d0f6 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-accept.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-accept.c @@ -65,7 +65,7 @@ int test_accept_on_accept (int fd_a) if (fd_b == -1) return -1; - int fd_c = accept (fd_b, NULL, 0); /* { dg-warning "'accept' on file descriptor 'fd_b' in wrong phase \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ + int fd_c = accept (fd_b, NULL, 0); /* { dg-warning "'accept' on file descriptor 'fd_b' in wrong phase \\\[CWE-666\\\] \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ /* { dg-message "'accept' expects a listening stream socket file descriptor but 'fd_b' is connected" "final event" { target *-*-* } .-1 } */ return fd_b; diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-bind.c b/gcc/testsuite/gcc.dg/analyzer/fd-bind.c index 2a5cee582301..2f69841bfd2a 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-bind.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-bind.c @@ -35,7 +35,7 @@ void test_double_bind (int fd, const char *sockname) addr.sun_family = AF_UNIX; strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1); bind (fd, (struct sockaddr *)&addr, sizeof (addr)); - bind (fd, (struct sockaddr *)&addr, sizeof (addr)); /* { dg-warning "'bind' on file descriptor 'fd' in wrong phase \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ + bind (fd, (struct sockaddr *)&addr, sizeof (addr)); /* { dg-warning "'bind' on file descriptor 'fd' in wrong phase \\\[CWE-666\\\] \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ /* { dg-message "'bind' expects a new socket file descriptor but 'fd' has already been bound" "final event" { target *-*-* } .-1 } */ } @@ -71,7 +71,7 @@ void test_bind_after_accept (int fd, const char *sockname) memset (&addr, 0, sizeof (addr)); addr.sun_family = AF_UNIX; strncpy (addr.sun_path, sockname, sizeof(addr.sun_path) - 1); - bind (afd, (struct sockaddr *)&addr, sizeof (addr)); /* { dg-warning "'bind' on file descriptor 'afd' in wrong phase \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ + bind (afd, (struct sockaddr *)&addr, sizeof (addr)); /* { dg-warning "'bind' on file descriptor 'afd' in wrong phase \\\[CWE-666\\\] \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ /* { dg-message "'bind' expects a new socket file descriptor but 'afd' is already connected" "final event" { target *-*-* } .-1 } */ close (afd); diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c b/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c index 87e8967ff21b..914948644bbc 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c @@ -18,7 +18,7 @@ void test_read_on_new_socket (void *buf) int fd = socket (AF_UNIX, SOCK_STREAM, 0); /* { dg-message "stream socket created here" } */ if (fd == -1) return; - read (fd, buf, 1); /* { dg-warning "'read' on file descriptor 'fd' in wrong phase \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ + read (fd, buf, 1); /* { dg-warning "'read' on file descriptor 'fd' in wrong phase \\\[CWE-666\\\] \\\[-Wanalyzer-fd-phase-mismatch\\\]" "warning" } */ /* { dg-message "'read' expects a stream socket to be connected via 'accept' but 'fd' has not yet been bound" "final event" { target *-*-* } .-1 } */ close (fd); } diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c index a364c8a678b9..b5814dd709eb 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c @@ -310,18 +310,16 @@ public: } bool - emit (rich_location *rich_loc, logger *) final override + emit (diagnostic_emission_context &ctxt) final override { - diagnostic_metadata m; bool warned; // just assuming constants for now auto actual_refcnt = m_actual_refcnt->dyn_cast_constant_svalue ()->get_constant (); auto ob_refcnt = m_ob_refcnt->dyn_cast_constant_svalue ()->get_constant (); - warned = warning_meta (rich_loc, m, get_controlling_option (), - "expected %qE to have " - "reference count: %qE but ob_refcnt field is: %qE", - m_reg_tree, actual_refcnt, ob_refcnt); + warned = ctxt.warn ("expected %qE to have " + "reference count: %qE but ob_refcnt field is: %qE", + m_reg_tree, actual_refcnt, ob_refcnt); // location_t loc = rich_loc->get_loc (); // foo (loc); diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c index e0fc9cd3e478..6ea6c03e1d52 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c @@ -155,10 +155,9 @@ class double_save_thread : public gil_diagnostic return m_call == sub_other.m_call; } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - return warning_at (rich_loc, get_controlling_option (), - "nested usage of %qs", "Py_BEGIN_ALLOW_THREADS"); + return ctxt.warn ("nested usage of %qs", "Py_BEGIN_ALLOW_THREADS"); } label_text describe_final_event (const evdesc::final_event &ev) final override @@ -194,19 +193,16 @@ class fncall_without_gil : public gil_diagnostic && m_arg_idx == sub_other.m_arg_idx); } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - auto_diagnostic_group d; if (m_callee_fndecl) - return warning_at (rich_loc, get_controlling_option (), - "use of PyObject as argument %i of %qE" - " without the GIL", - m_arg_idx + 1, m_callee_fndecl); + return ctxt.warn ("use of PyObject as argument %i of %qE" + " without the GIL", + m_arg_idx + 1, m_callee_fndecl); else - return warning_at (rich_loc, get_controlling_option (), - "use of PyObject as argument %i of call" - " without the GIL", - m_arg_idx + 1, m_callee_fndecl); + return ctxt.warn ("use of PyObject as argument %i of call" + " without the GIL", + m_arg_idx + 1, m_callee_fndecl); } label_text describe_final_event (const evdesc::final_event &ev) final override @@ -245,11 +241,9 @@ class pyobject_usage_without_gil : public gil_diagnostic ((const pyobject_usage_without_gil&)base_other).m_expr); } - bool emit (rich_location *rich_loc, logger *) final override + bool emit (diagnostic_emission_context &ctxt) final override { - auto_diagnostic_group d; - return warning_at (rich_loc, get_controlling_option (), - "use of PyObject %qE without the GIL", m_expr); + return ctxt.warn ("use of PyObject %qE without the GIL", m_expr); } label_text describe_final_event (const evdesc::final_event &ev) final override -- 2.43.5