aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/engine.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2022-08-05 19:45:41 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2022-08-05 19:45:41 -0400
commite1a9168153d2bf12695844a9ca9f9fc1de8d1ddf (patch)
tree1ec0493d1273a4b4e8abaf2ee23d13be64ffffc9 /gcc/analyzer/engine.cc
parentcc01a27db5411a4fe354a97b7c86703c5bc81243 (diff)
downloadgcc-e1a9168153d2bf12695844a9ca9f9fc1de8d1ddf.zip
gcc-e1a9168153d2bf12695844a9ca9f9fc1de8d1ddf.tar.gz
gcc-e1a9168153d2bf12695844a9ca9f9fc1de8d1ddf.tar.bz2
New warning: -Wanalyzer-jump-through-null [PR105947]
This patch adds a new warning to -fanalyzer for jumps through NULL function pointers. gcc/analyzer/ChangeLog: PR analyzer/105947 * analyzer.opt (Wanalyzer-jump-through-null): New option. * engine.cc (class jump_through_null): New. (exploded_graph::process_node): Complain about jumps through NULL function pointers. gcc/ChangeLog: PR analyzer/105947 * doc/invoke.texi: Add -Wanalyzer-jump-through-null. gcc/testsuite/ChangeLog: PR analyzer/105947 * gcc.dg/analyzer/function-ptr-5.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/analyzer/engine.cc')
-rw-r--r--gcc/analyzer/engine.cc49
1 files changed, 49 insertions, 0 deletions
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 85b7c5e..e8db00d 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -3705,6 +3705,46 @@ private:
bool m_terminate_path;
};
+/* A subclass of pending_diagnostic for complaining about jumps through NULL
+ function pointers. */
+
+class jump_through_null : public pending_diagnostic_subclass<jump_through_null>
+{
+public:
+ jump_through_null (const gcall *call)
+ : m_call (call)
+ {}
+
+ const char *get_kind () const final override
+ {
+ return "jump_through_null";
+ }
+
+ bool operator== (const jump_through_null &other) const
+ {
+ return m_call == other.m_call;
+ }
+
+ int get_controlling_option () const final override
+ {
+ return OPT_Wanalyzer_jump_through_null;
+ }
+
+ bool emit (rich_location *rich_loc) final override
+ {
+ return warning_at (rich_loc, get_controlling_option (),
+ "jump through null pointer");
+ }
+
+ label_text describe_final_event (const evdesc::final_event &ev) final override
+ {
+ return ev.formatted_print ("jump through null pointer here");
+ }
+
+private:
+ const gcall *m_call;
+};
+
/* The core of exploded_graph::process_worklist (the main analysis loop),
handling one node in the worklist.
@@ -4046,6 +4086,15 @@ exploded_graph::process_node (exploded_node *node)
logger);
if (!call_discovered)
{
+ /* Check for jump through NULL. */
+ if (tree fn_ptr = gimple_call_fn (call))
+ {
+ const svalue *fn_ptr_sval
+ = model->get_rvalue (fn_ptr, &ctxt);
+ if (fn_ptr_sval->all_zeroes_p ())
+ ctxt.warn (new jump_through_null (call));
+ }
+
/* An unknown function or a special function was called
at this point, in such case, don't terminate the
analysis of the current function.