[PATCH] evaluate: fix dereferencing function pointers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If you dereference a function pointer, you get a function pointer back.
AFAICS there are >=69 places in the kernel that unnecessarily dereference a
function pointer before calling through it.

Output of testcase when applied to previous version:

=============================================
$ ./test-suite single linear/fn-ptr-deref.c
     TEST    dereference function pointer (linear/fn-ptr-deref.c)
error: actual output text does not match expected output text.
error: see linear/fn-ptr-deref.c.output.* for further investigation.
--- linear/fn-ptr-deref.c.output.expected	2018-02-22 01:26:20.592985408 +0100
+++ linear/fn-ptr-deref.c.output.got	2018-02-22 01:26:20.588985440 +0100
@@ -2,7 +2,8 @@
 .L0:
 	<entry-point>
 	call        func_a
-	call        func_a
+	load        %r4 <- 0[func_a]
+	call        VOID
 	ret


linear/fn-ptr-deref.c failed !
=============================================

Signed-off-by: Jann Horn <jannh@xxxxxxxxxx>
---
 evaluate.c                       |  6 ++++++
 validation/linear/fn-ptr-deref.c | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 validation/linear/fn-ptr-deref.c

diff --git a/evaluate.c b/evaluate.c
index b96696d..3859bfc 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1776,6 +1776,12 @@ static struct symbol *evaluate_dereference(struct expression *expr)
 	if (ctype->type == SYM_NODE)
 		ctype = ctype->ctype.base_type;
 
+	/* Dereferencing a function pointer does nothing. */
+	if (ctype->type == SYM_PTR && ctype->ctype.base_type->type == SYM_FN) {
+		*expr = *op;
+		return expr->ctype;
+	}
+
 	node = alloc_symbol(expr->pos, SYM_NODE);
 	target = ctype->ctype.base_type;
 
diff --git a/validation/linear/fn-ptr-deref.c b/validation/linear/fn-ptr-deref.c
new file mode 100644
index 0000000..9352d1e
--- /dev/null
+++ b/validation/linear/fn-ptr-deref.c
@@ -0,0 +1,22 @@
+void func_a(void);
+static void function_foobar(int n)
+{
+	void (*indir_func_var)(void) = func_a;
+	indir_func_var();
+	(*indir_func_var)();
+}
+/*
+ * check-name: dereference function pointer
+ * check-command: test-linearize $file
+ *
+ * check-output-start
+function_foobar:
+.L0:
+	<entry-point>
+	call        func_a
+	call        func_a
+	ret
+
+
+ * check-output-end
+ */
-- 
2.16.1.291.g4437f3f132-goog

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux