diff options
author | Xavier Leroy <xavier.leroy@inria.fr> | 2015-07-19 17:08:17 +0200 |
---|---|---|
committer | Xavier Leroy <xavier.leroy@inria.fr> | 2015-07-19 17:35:54 +0200 |
commit | 26f63d2d82d22f568ba44d12d396acca8aa11613 (patch) | |
tree | d3f73d604b03958434c8527ee059ac728e5c164b | |
parent | 78f1b6a57c95ecc68c104d4764fc8d5851d7dd54 (diff) | |
download | compcert-26f63d2d82d22f568ba44d12d396acca8aa11613.tar.gz compcert-26f63d2d82d22f568ba44d12d396acca8aa11613.zip |
Test to check that alias analysis is prudently conservative on ill-defined pointer manipulations.
-rw-r--r-- | test/regression/Makefile | 2 | ||||
-rw-r--r-- | test/regression/Results/alias | 7 | ||||
-rw-r--r-- | test/regression/alias.c | 145 |
3 files changed, 153 insertions, 1 deletions
diff --git a/test/regression/Makefile b/test/regression/Makefile index e2d94aa9..00c80047 100644 --- a/test/regression/Makefile +++ b/test/regression/Makefile @@ -24,7 +24,7 @@ TESTS=int32 int64 floats floats-basics \ TESTS_COMP=attribs1 bitfields1 bitfields2 bitfields3 bitfields4 \ bitfields5 bitfields6 bitfields7 bitfields8 \ builtins-$(ARCH) packedstruct1 packedstruct2 alignas \ - varargs1 varargs2 sections + varargs1 varargs2 sections alias # Can run, both in compiled mode and in interpreter mode, # but produce processor-dependent results, so no reference output in Results diff --git a/test/regression/Results/alias b/test/regression/Results/alias new file mode 100644 index 00000000..4f34918d --- /dev/null +++ b/test/regression/Results/alias @@ -0,0 +1,7 @@ +Test 1: 1 +Test 2: 1 +Test 3: 1 +Test 4: 1 +Test 5: 1 +Test 6: 1 +Test 7: 1 diff --git a/test/regression/alias.c b/test/regression/alias.c new file mode 100644 index 00000000..c9eb8130 --- /dev/null +++ b/test/regression/alias.c @@ -0,0 +1,145 @@ +/* Testing the alias analysis on ill-defined codes + where it should remain conservative. */ + +typedef unsigned int uintptr_t; + +/* For testing with GCC */ +#define NOINLINE __attribute__((noinline)) + +/* Passing a pointer through a long long */ + +void NOINLINE set1(long long x) +{ + int * p = (int *) (uintptr_t) x; + *p = 1; +} + +int get1(void) +{ + int x = 0; + set1((uintptr_t) &x); + return x; +} + +/* Passing a pointer through a double */ + +void NOINLINE set2(double x) +{ + int * p = (int *) (uintptr_t) x; + *p = 1; +} + +int get2(void) +{ + int x = 0; + set2((uintptr_t) &x); + return x; +} + +/* Tagging a pointer */ + +void NOINLINE set3(uintptr_t x) +{ + int * p = (int *) (x & ~1); + *p = 1; +} + +int get3(void) +{ + int x = 0; + set3((uintptr_t) &x | 1); + return x; +} + +/* XOR-ing a pointer */ + +static uintptr_t key = 0xDEADBEEF; + +void NOINLINE set4(uintptr_t x) +{ + int * p = (int *) (x ^ key); + *p = 1; +} + +int get4(void) +{ + int x = 0; + set4((uintptr_t) &x ^ key); + return x; +} + +/* Byte-swapping a pointer */ + +inline uintptr_t bswap(uintptr_t x) +{ + return (x >> 24) + | (((x >> 16) & 0xFF) << 8) + | (((x >> 8) & 0xFF) << 16) + | ((x & 0xFF) << 24); +} + +void NOINLINE set5(uintptr_t x) +{ + int * p = (int *) bswap(x); + *p = 1; +} + +int get5(void) +{ + int x = 0; + set5(bswap((uintptr_t) &x)); + return x; +} + +/* Even more fun with xor */ + +int x; + +void NOINLINE set6(int * p, uintptr_t z) +{ + int * q = (int *) ((uintptr_t) p ^ z); + *q = 1; +} + +int get6(void) +{ + int y = 0; + uintptr_t z = (uintptr_t) &x ^ (uintptr_t) &y; + set6(&x, z); + int res1 = y; + x = 0; + set6(&y, z); + int res2 = x; + return res1 & res2; +} + +/* Aligning pointers the hard way */ + +int offset = 3; /* but not const */ + +int get7(void) +{ + union { int i; char c[4]; } u; /* force alignment to 4 */ + u.c[0] = 0; + uintptr_t x = (uintptr_t) &(u.c[offset]); + x = x & ~3; + *((char *) x) = 1; + return u.c[0]; +} + +/* Test harness */ + +#include <stdio.h> + +int main() +{ + printf("Test 1: %d\n", get1()); + printf("Test 2: %d\n", get2()); + printf("Test 3: %d\n", get3()); + printf("Test 4: %d\n", get4()); + printf("Test 5: %d\n", get5()); + printf("Test 6: %d\n", get6()); + printf("Test 7: %d\n", get7()); + return 0; +} + |