aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-08-13 06:15:36 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-08-17 05:18:37 +0200
commitb987e1d1319678d87049f415acd2ce16ba5e5263 (patch)
tree4b52b4247ceb1cf5dd781e1932d7d19c6b1561fe
parent49f7e13a7ac9a582d11e9c1ad01e71740f486601 (diff)
downloadsparse-b987e1d1319678d87049f415acd2ce16ba5e5263.tar.gz
fix evaluate_ptr_add() when sizeof(offset) != sizeof(pointer)
For a binary op, both sides need to be converted to the resulting type of the usual conversion. For a compound-assignment (which is equivalent to a binary op followed by an assignment), the LHS can't be so converted since its type needs to be preserved for the assignment, so only the RHS is converted at evaluation and the type of the RHS is used at linearization to convert the LHS. However, in the case of pointer arithmetics, a number of shortcuts are taken and as a result additions with mixed sizes can be produced producing invalid IR. So, fix this by converting the RHS to the same size as pointers, as done for 'normal' binops. Note: On 32-bit kernel, this patch also removes a few warnings about non size-preserving casts. It's fine as these warnings were designed for when an address would be stored in an integer, not for storing an offset like it's the case here. Reported-by: Valentin Schneider <valentin.schneider@arm.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--evaluate.c4
-rw-r--r--validation/linear/pointer-arith32.c94
-rw-r--r--validation/linear/pointer-arith64.c79
3 files changed, 175 insertions, 2 deletions
diff --git a/evaluate.c b/evaluate.c
index 63a9390b..1839e35d 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -619,7 +619,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *i
ctype = &ptr_ctype;
expr->ctype = ctype;
- if (multiply == 1 && itype->bit_size >= bits_in_pointer)
+ if (multiply == 1 && itype->bit_size == bits_in_pointer)
return ctype;
if (index->type == EXPR_VALUE) {
@@ -639,7 +639,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *i
return ctype;
}
- if (itype->bit_size < bits_in_pointer)
+ if (itype->bit_size != bits_in_pointer)
index = cast_to(index, ssize_t_ctype);
if (multiply > 1) {
diff --git a/validation/linear/pointer-arith32.c b/validation/linear/pointer-arith32.c
new file mode 100644
index 00000000..531fd232
--- /dev/null
+++ b/validation/linear/pointer-arith32.c
@@ -0,0 +1,94 @@
+char *cps(char *data, short pos)
+{
+ data += pos;
+ return data;
+}
+
+int *ipss(int *data, short pos)
+{
+ data += pos;
+ return data;
+}
+int *ipus(int *data, unsigned short pos)
+{
+ data += pos;
+ return data;
+}
+
+char *cpq(char *data, long long pos)
+{
+ data += pos;
+ return data;
+}
+
+int *ipq_ref(int *data, long long pos)
+{
+ data = data + pos;
+ return data;
+}
+
+int *ipq(int *data, long long pos)
+{
+ data += pos;
+ return data;
+}
+
+/*
+ * check-name: pointer-arith32
+ * check-command: test-linearize -Wno-decl --arch=generic -m32 $file
+ *
+ * check-output-start
+cps:
+.L0:
+ <entry-point>
+ sext.32 %r2 <- (16) %arg2
+ add.32 %r5 <- %arg1, %r2
+ ret.32 %r5
+
+
+ipss:
+.L2:
+ <entry-point>
+ sext.32 %r10 <- (16) %arg2
+ mul.32 %r11 <- %r10, $4
+ add.32 %r14 <- %arg1, %r11
+ ret.32 %r14
+
+
+ipus:
+.L4:
+ <entry-point>
+ zext.32 %r19 <- (16) %arg2
+ mul.32 %r20 <- %r19, $4
+ add.32 %r23 <- %arg1, %r20
+ ret.32 %r23
+
+
+cpq:
+.L6:
+ <entry-point>
+ trunc.32 %r28 <- (64) %arg2
+ add.32 %r31 <- %arg1, %r28
+ ret.32 %r31
+
+
+ipq_ref:
+.L8:
+ <entry-point>
+ trunc.32 %r37 <- (64) %arg2
+ mul.32 %r38 <- %r37, $4
+ add.32 %r39 <- %arg1, %r38
+ ret.32 %r39
+
+
+ipq:
+.L10:
+ <entry-point>
+ trunc.32 %r43 <- (64) %arg2
+ mul.32 %r44 <- %r43, $4
+ add.32 %r47 <- %arg1, %r44
+ ret.32 %r47
+
+
+ * check-output-end
+ */
diff --git a/validation/linear/pointer-arith64.c b/validation/linear/pointer-arith64.c
new file mode 100644
index 00000000..dad10331
--- /dev/null
+++ b/validation/linear/pointer-arith64.c
@@ -0,0 +1,79 @@
+char *cps(char *data, short pos)
+{
+ data += pos;
+ return data;
+}
+
+int *ipss(int *data, short pos)
+{
+ data += pos;
+ return data;
+}
+int *ipus(int *data, unsigned short pos)
+{
+ data += pos;
+ return data;
+}
+
+int *ipsi(int *data, int pos)
+{
+ data += pos;
+ return data;
+}
+int *ipui(int *data, unsigned int pos)
+{
+ data += pos;
+ return data;
+}
+
+/*
+ * check-name: pointer-arith64
+ * check-command: test-linearize -Wno-decl --arch=generic -m64 $file
+ *
+ * check-output-start
+cps:
+.L0:
+ <entry-point>
+ sext.64 %r2 <- (16) %arg2
+ add.64 %r5 <- %arg1, %r2
+ ret.64 %r5
+
+
+ipss:
+.L2:
+ <entry-point>
+ sext.64 %r10 <- (16) %arg2
+ mul.64 %r11 <- %r10, $4
+ add.64 %r14 <- %arg1, %r11
+ ret.64 %r14
+
+
+ipus:
+.L4:
+ <entry-point>
+ zext.64 %r19 <- (16) %arg2
+ mul.64 %r20 <- %r19, $4
+ add.64 %r23 <- %arg1, %r20
+ ret.64 %r23
+
+
+ipsi:
+.L6:
+ <entry-point>
+ sext.64 %r28 <- (32) %arg2
+ mul.64 %r29 <- %r28, $4
+ add.64 %r32 <- %arg1, %r29
+ ret.64 %r32
+
+
+ipui:
+.L8:
+ <entry-point>
+ zext.64 %r37 <- (32) %arg2
+ mul.64 %r38 <- %r37, $4
+ add.64 %r41 <- %arg1, %r38
+ ret.64 %r41
+
+
+ * check-output-end
+ */