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 <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm 2023-12-01 08:47:41 -05:00
parent 83b210d55b
commit 12b67d1e13
32 changed files with 550 additions and 533 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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?

View File

@ -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 ();

View File

@ -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;

View File

@ -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

View File

@ -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 &,

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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. */

View File

@ -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.

View File

@ -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 %<free%> of %qE",
m_expr);
ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
return ctxt.warn ("use after %<free%> 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 %<delete%> of %qE",
m_expr);
ctxt.add_cwe (416); /* "CWE-416: Use After Free". */
return ctxt.warn ("use after %<delete%> 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 %<const%> object %qE", m_decl);
warned = ctxt.warn ("write to %<const%> 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
{

View File

@ -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"

View File

@ -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 %<close%> of file descriptor %qE", m_arg);
ctxt.add_cwe (1341);
return ctxt.warn ("double %<close%> 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);
}
}

View File

@ -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 %<fclose%> of FILE %qE",
m_arg);
ctxt.add_cwe (1341);
return ctxt.warn ("double %<fclose%> 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)

View File

@ -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", "<unknown>");
return ctxt.warn ("leak of %qs", "<unknown>");
}
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)

View File

@ -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:

View File

@ -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)

View File

@ -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. */

View File

@ -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,

View File

@ -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"

View File

@ -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 (),
"%<va_arg%> 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 ("%<va_arg%> 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;
}

View File

@ -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

View File

@ -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))

View File

@ -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; }

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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