summaryrefslogtreecommitdiff
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
parentcc01a27db5411a4fe354a97b7c86703c5bc81243 (diff)
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>
-rw-r--r--gcc/analyzer/analyzer.opt4
-rw-r--r--gcc/analyzer/engine.cc49
-rw-r--r--gcc/doc/invoke.texi12
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/function-ptr-5.c42
4 files changed, 107 insertions, 0 deletions
diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index 808ff36ac54..c6d9c53d9c3 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -98,6 +98,10 @@ Wanalyzer-free-of-non-heap
Common Var(warn_analyzer_free_of_non_heap) Init(1) Warning
Warn about code paths in which a non-heap pointer is freed.
+Wanalyzer-jump-through-null
+Common Var(warn_analyzer_jump_through_null) Init(1) Warning
+Warn about code paths in which a NULL function pointer is called.
+
Wanalyzer-malloc-leak
Common Var(warn_analyzer_malloc_leak) Init(1) Warning
Warn about code paths in which a heap-allocated pointer leaks.
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 85b7c5e1227..e8db00d7e18 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.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 863580b3710..92f7aaead74 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -453,6 +453,7 @@ Objective-C and Objective-C++ Dialects}.
-Wno-analyzer-fd-use-without-check @gol
-Wno-analyzer-file-leak @gol
-Wno-analyzer-free-of-non-heap @gol
+-Wno-analyzer-jump-through-null @gol
-Wno-analyzer-malloc-leak @gol
-Wno-analyzer-mismatching-deallocation @gol
-Wno-analyzer-null-argument @gol
@@ -9756,6 +9757,7 @@ Enabling this option effectively enables the following warnings:
-Wanalyzer-fd-use-without-check @gol
-Wanalyzer-file-leak @gol
-Wanalyzer-free-of-non-heap @gol
+-Wanalyzer-jump-through-null @gol
-Wanalyzer-malloc-leak @gol
-Wanalyzer-mismatching-deallocation @gol
-Wanalyzer-null-argument @gol
@@ -9942,6 +9944,16 @@ is called on a non-heap pointer (e.g. an on-stack buffer, or a global).
See @uref{https://cwe.mitre.org/data/definitions/590.html, CWE-590: Free of Memory not on the Heap}.
+@item -Wno-analyzer-jump-through-null
+@opindex Wanalyzer-jump-through-null
+@opindex Wno-analyzer-jump-through-null
+This warning requires @option{-fanalyzer}, which enables it; use
+@option{-Wno-analyzer-jump-through-null}
+to disable it.
+
+This diagnostic warns for paths through the code in which a @code{NULL}
+function pointer is called.
+
@item -Wno-analyzer-malloc-leak
@opindex Wanalyzer-malloc-leak
@opindex Wno-analyzer-malloc-leak
diff --git a/gcc/testsuite/gcc.dg/analyzer/function-ptr-5.c b/gcc/testsuite/gcc.dg/analyzer/function-ptr-5.c
new file mode 100644
index 00000000000..3c46f289082
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/function-ptr-5.c
@@ -0,0 +1,42 @@
+#define NULL ((void *)0)
+
+void calling_null_fn_ptr_1 (void)
+{
+ void (*fn_ptr) (void) = NULL;
+ fn_ptr (); /* { dg-warning "jump through null pointer" } */
+}
+
+int calling_null_fn_ptr_2 (void)
+{
+ int (*fn_ptr) (void) = NULL;
+ return fn_ptr (); /* { dg-warning "jump through null pointer" } */
+}
+
+typedef void (*void_void_fn_ptr) (void);
+
+void calling_const_fn_ptr (void)
+{
+ void_void_fn_ptr fn_ptr = (void_void_fn_ptr)0xffd2;
+ return fn_ptr ();
+}
+
+void skipping_init (int flag)
+{
+ void_void_fn_ptr fn_ptr = NULL;
+ if (flag) /* { dg-message "branch" } */
+ fn_ptr = (void_void_fn_ptr)0xffd2;
+ fn_ptr (); /* { dg-warning "jump through null pointer" } */
+}
+
+struct callbacks
+{
+ void_void_fn_ptr on_redraw;
+ void_void_fn_ptr on_cleanup;
+};
+
+void test_callbacks (void)
+{
+ struct callbacks cb;
+ __builtin_memset (&cb, 0, sizeof (cb));
+ cb.on_cleanup (); /* { dg-warning "jump through null pointer" } */
+}