blob: 5c3e691c9d65fe9ebb7d49aa1aeebd4f01fa60d6 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// REQUIRES: geq-llvm-11.0
/* 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;
}
|