about summary refs log tree commit diff homepage
path: root/test/VectorInstructions/oob-write.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/VectorInstructions/oob-write.c')
-rw-r--r--test/VectorInstructions/oob-write.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/test/VectorInstructions/oob-write.c b/test/VectorInstructions/oob-write.c
new file mode 100644
index 00000000..6906dc62
--- /dev/null
+++ b/test/VectorInstructions/oob-write.c
@@ -0,0 +1,49 @@
+/* The scalarizer pass in LLVM 11 was changed to generate, for a
+ write of the form f[k] = v, with f a 4-element vector:
+ if k == 0 => f[0] = v
+ if k == 1 => f[1] = v
+ if k == 2 => f[2] = v
+ if k == 3 => f[3] = v
+
+ Therefore, even though an OOB write access might exist at the source
+ code level (e.g., f[5] = v), no such OOB accesses exist anymore at
+ the LLVM IR level.
+
+ So unlike in the LLVM < 11 test, here we test that the contents of
+ the vector is unmodified after the OOB write.
+*/
+
+// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// NOTE: Have to pass `--optimize=false` to avoid vector operations being
+// constant folded away.
+// RUN: %klee --output-dir=%t.klee-out --optimize=false --exit-on-error %t1.bc
+
+#include "klee/klee.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+typedef uint32_t v4ui __attribute__((vector_size(16)));
+int main() {
+  v4ui f = {1, 2, 3, 4};
+  int k = klee_range(0, 10, "k");
+
+  if (k < 4) {
+    f[5] = 3; // Concrete out-of-bounds write
+    assert(f[0] == 1);
+    assert(f[1] == 2);
+    assert(f[2] == 3);
+    assert(f[3] == 4);
+  }
+  else {
+    f[k] = 255; // Symbolic out-of-bounds write
+    assert(f[0] == 1);
+    assert(f[1] == 2);
+    assert(f[2] == 3);
+    assert(f[3] == 4); 
+  }
+
+  return 0;
+}