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>
This commit is contained in:
parent
cc01a27db5
commit
e1a9168153
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" } */
|
||||
}
|
Loading…
Reference in New Issue