aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/validation
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-06-15 14:48:41 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-06-15 21:16:55 +0200
commit57d04233adb124caf4df759b8f3cdc582f985262 (patch)
tree02dbe14f58349010d5b6966e7ffb62b9e45d9568 /validation
parentbcfe020ed939fa1e8474efaf31a86d80d0e5c5fe (diff)
downloadsparse-dev-57d04233adb124caf4df759b8f3cdc582f985262.tar.gz
fix: add missing examine in evaluate_dereference()
sparse use lazy type evaluation. This evaluation is done via the examine_*() functions, which we must insure to have been called when type information is needed. However, it seems that this is not done for expressions with multiple level of dereferencing. There is (at least) two symptoms: 1) When the inner expression is complex and contains a typeof: a bogus error message is issued, either "error: internal error: bad type in derived(11)" or "error: cannot dereference this type", sometimes followed by another bogus "warning: unknown expression (...)". 2) This one is only visible with test-linearize but happen even on a plain double deref: the result of the inner deref is typeless. Obviously the first symptom is a consequence of the second one. Fix this by adding a call to examine_symbol_type() at the beginning of evaluate_dereference(). Note: This fixes all the 17 "cannot dereference" and 19 "internal error" present on the Linux kernel while using sparse on a x86-64 allyesconfig (most coming from the call of rcu_dereference_sched() in cpufreq_update_util()). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'validation')
-rw-r--r--validation/badtype5.c18
-rw-r--r--validation/linear/missing-insn-size.c19
2 files changed, 37 insertions, 0 deletions
diff --git a/validation/badtype5.c b/validation/badtype5.c
new file mode 100644
index 00000000..c3c34ab2
--- /dev/null
+++ b/validation/badtype5.c
@@ -0,0 +1,18 @@
+#define __force __attribute__((force))
+
+int foo(int *addr);
+int foo(int *addr)
+{
+ return *(*((typeof(addr) __force *) addr));
+}
+
+/*
+ * check-name: badtype5.c
+ * check-description:
+ * evaluate_dereference() used to miss a call to
+ * examine_symbol_type(). This, in the present, left
+ * a SYM_TYPEOF as type for the last dereferencing
+ * which produced "error: cannot dereference this type".
+ * The presence of the __force and the typeof is needed
+ * to create the situation.
+ */
diff --git a/validation/linear/missing-insn-size.c b/validation/linear/missing-insn-size.c
new file mode 100644
index 00000000..fe588634
--- /dev/null
+++ b/validation/linear/missing-insn-size.c
@@ -0,0 +1,19 @@
+int foo(int **a);
+int foo(int **a)
+{
+ return **a;
+}
+
+/*
+ * check-name: missing instruction's size
+ * check-description:
+ * sparse used to have a problem with *all*
+ * double dereferencing due to missing a
+ * call to examine_symbol_type(). The symptom
+ * here is that the inner deref had no type.
+ * check-command: test-linearize $file
+ * check-output-ignore
+ *
+ * check-output-excludes: load\\s
+ * check-output-contains: load\\.
+ */