aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/sm-malloc.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-12-01 08:47:41 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2023-12-01 08:47:41 -0500
commit12b67d1e13b3cf14fb24cf2a1c008b73d377ff6d (patch)
tree4ad4d9f5e959e18e32a33726c3da47668220593c /gcc/analyzer/sm-malloc.cc
parent83b210d55b28461e7604068c5df95a24b21e7081 (diff)
downloadgcc-12b67d1e13b3cf14fb24cf2a1c008b73d377ff6d.zip
gcc-12b67d1e13b3cf14fb24cf2a1c008b73d377ff6d.tar.gz
gcc-12b67d1e13b3cf14fb24cf2a1c008b73d377ff6d.tar.bz2
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>
Diffstat (limited to 'gcc/analyzer/sm-malloc.cc')
-rw-r--r--gcc/analyzer/sm-malloc.cc118
1 files changed, 47 insertions, 71 deletions
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 5af6544..bb78444 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", "<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)