Dynamic bounds check of arrays at assignment (#125)
This commit slightly reorganises the dynamic_checking directory, and duplicates the deref tests to make them test using a checked array/array_ptr on the left side of an assignment operator.
This commit is contained in:
Родитель
c2cf77e4ca
Коммит
ec6d087122
|
@ -1,40 +0,0 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks and pointer arithmetic
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `deref-arith-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `deref-arith-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/deref-arith-check.c -o %t -Werror -O3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %S/deref-arith-check.c
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %S/deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %S/deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %S/deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %S/deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %S/deref-arith-check.c
|
||||
// RUN: %t 3 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %S/deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `deref-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `deref-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/deref-check.c -o %t -Werror -O3
|
||||
// RUN: %t pass1 | FileCheck %S/deref-check.c --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-1
|
||||
// RUN: %t pass2 | FileCheck %S/deref-check.c --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-2
|
||||
// RUN: %t fail1 | FileCheck %S/deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-1
|
||||
// RUN: %t fail2 | FileCheck %S/deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-2
|
||||
// RUN: %t fail3 | FileCheck %S/deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-3
|
||||
// RUN: %t fail4 | FileCheck %S/deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-4
|
||||
|
||||
#import <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks and pointer arithmetic
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `read-deref-arith-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `read-deref-arith-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/read-deref-arith-check.c -o %t -Werror -O3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %S/read-deref-arith-check.c
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %S/read-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %S/read-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %S/read-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %S/read-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %S/read-deref-arith-check.c
|
||||
// RUN: %t 3 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %S/read-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `read-deref-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `read-deref-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/read-deref-check.c -o %t -Werror -O3
|
||||
// RUN: %t pass1 | FileCheck %S/read-deref-check.c --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-1
|
||||
// RUN: %t pass2 | FileCheck %S/read-deref-check.c --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-2
|
||||
// RUN: %t fail1 | FileCheck %S/read-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-1
|
||||
// RUN: %t fail2 | FileCheck %S/read-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-2
|
||||
// RUN: %t fail3 | FileCheck %S/read-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-3
|
||||
// RUN: %t fail4 | FileCheck %S/read-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-4
|
||||
|
||||
#import <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Tests that the Array Subscript Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `read-subscript-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `read-subscript-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/read-subscript-check.c -o %t -Werror -O3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %S/read-subscript-check.c
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %S/read-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %S/read-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %S/read-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %S/read-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %S/read-subscript-check.c
|
||||
// RUN: %t 3 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %S/read-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
// Don't run this file
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// Tests that the Array Subscript Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `subscript-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `subscript-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/subscript-check.c -o %t -Werror -O3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %S/subscript-check.c
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %S/subscript-check.c
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %S/subscript-check.c
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %S/subscript-check.c
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %S/subscript-check.c
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %S/subscript-check.c
|
||||
// RUN: %t 3 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %S/subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
// Don't run this file
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks and pointer arithmetic
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `write-deref-arith-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `write-deref-arith-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/write-deref-arith-check.c -o %t -Werror -O3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %S/write-deref-arith-check.c
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %S/write-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %S/write-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %S/write-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %S/write-deref-arith-check.c
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %S/write-deref-arith-check.c
|
||||
// RUN: %t 3 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %S/write-deref-arith-check.c --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks and pointer arithmetic
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %s -o %t -Werror
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %s
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %s
|
||||
// RUN: %t 3 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "../../include/stdchecked.h"
|
||||
|
||||
int a0 checked[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
int ma1 checked[3][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };
|
||||
int ma2 checked[3][3][3] = {
|
||||
{ { 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 } },
|
||||
{ { 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 } },
|
||||
{ { 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 } }
|
||||
};
|
||||
|
||||
array_ptr<int> a1 : count(3) = a0;
|
||||
|
||||
// Handle an out-of-bounds reference by immediately exiting. This causes
|
||||
// some output to be missing.
|
||||
void handle_error(int err) {
|
||||
_Exit(0);
|
||||
}
|
||||
|
||||
// This signature for main is exactly what we want here,
|
||||
// it also means any uses of argv[i] are checked too!
|
||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||
|
||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
||||
// may change in the future.
|
||||
signal(SIGILL, handle_error);
|
||||
|
||||
// Unfortunately, using atoi everywhere below isn't super
|
||||
// great, as it will return 0 if it can't parse, which is a valid,
|
||||
// non-erroring index. This is why we use CHECK-*-NOT to make sure
|
||||
// the tests fail before getting to certain output.
|
||||
|
||||
// This makes sure output is not buffered for when
|
||||
// we hit errors.
|
||||
int err = setvbuf(stdout, NULL, _IONBF, 0);
|
||||
if (err) {
|
||||
// CHECK-NOT: Error Settinug Up Buffering
|
||||
puts("Error Setting Up Buffering");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int idx = 1;
|
||||
|
||||
// CHECK: Starting Test
|
||||
// CHECK-FAIL-1: Starting Test
|
||||
// CHECK-FAIL-2: Starting Test
|
||||
// CHECK-FAIL-3: Starting Test
|
||||
puts("Starting Test");
|
||||
|
||||
array_ptr<int> a2 : count(5) = a0;
|
||||
int a3 checked[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
int i = atoi(argv[idx++]);
|
||||
*(a1 + i) = i;
|
||||
printf("*(a1 + %d) = %d;\n", i, *(a1 + i));
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
*(a2 + i) = i;
|
||||
printf("*(a2 + %d) = %d;\n", i, *(a2 + i));
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
*(a3 + i) = i;
|
||||
printf("*(a3 + %d) = %d;\n", i, *(a3 + i));
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
*(a0 + i) = i;
|
||||
printf("*(a0 + %d) = %d;\n", i, *(a0 + i));
|
||||
|
||||
// CHECK: 1-Dimensional Checks Passed
|
||||
// CHECK-FAIL-1-NOT: 1-Dimensional Checks Passed
|
||||
// CHECK-FAIL-2: 1-Dimensional Checks Passed
|
||||
// CHECK-FAIL-3: 1-Dimensional Checks Passed
|
||||
puts("1-Dimensional Checks Passed");
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
int j = atoi(argv[idx++]);
|
||||
*(*(ma1 + i) + j) = i + j;
|
||||
printf("*(*(ma1 + %d) + %d) = %d;\n", i, j, *(*(ma1 + i) + j));
|
||||
|
||||
// CHECK: 2-Dimensional Checks Passed
|
||||
// CHECK-FAIL-1-NOT: 2-Dimensional Checks Passed
|
||||
// CHECK-FAIL-2-NOT: 2-Dimensional Checks Passed
|
||||
// CHECK-FAIL-3: 2-Dimensional Checks Passed
|
||||
puts("2-Dimensional Checks Passed");
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
j = atoi(argv[idx++]);
|
||||
int k = atoi(argv[idx++]);
|
||||
*(*(*(ma2 + i) + j) + k) = i + j + k;
|
||||
printf("*(*(*(ma2 + %d) + %d) + %d) = %d;\n", i, j, k, *(*(*(ma2 + i) + j) + k));
|
||||
|
||||
|
||||
// CHECK: 3-Dimensional Checks Passed
|
||||
// CHECK-FAIL-1-NOT: 3-Dimensional Checks Passed
|
||||
// CHECK-FAIL-2-NOT: 3-Dimensional Checks Passed
|
||||
// CHECK-FAIL-3-NOT: 3-Dimensional Checks Passed
|
||||
puts("3-Dimensional Checks Passed");
|
||||
|
||||
// CHECK: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-1-NOT: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-2-NOT: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-3-NOT: All Dynamic Checks Passed
|
||||
puts("All Dynamic Checks Passed");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `write-deref-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `write-deref-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/write-deref-check.c -o %t -Werror -O3
|
||||
// RUN: %t pass1 | FileCheck %S/write-deref-check.c --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-1
|
||||
// RUN: %t pass2 | FileCheck %S/write-deref-check.c --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-2
|
||||
// RUN: %t fail1 | FileCheck %S/write-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-1
|
||||
// RUN: %t fail2 | FileCheck %S/write-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-2
|
||||
// RUN: %t fail3 | FileCheck %S/write-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-3
|
||||
// RUN: %t fail4 | FileCheck %S/write-deref-check.c --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-4
|
||||
|
||||
#import <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
// Tests that the Dereference Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %s -o %t -Werror
|
||||
// RUN: %t pass1 | FileCheck %s --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-1
|
||||
// RUN: %t pass2 | FileCheck %s --check-prefixes=CHECK,CHECK-PASS,CHECK-PASS-2
|
||||
// RUN: %t fail1 | FileCheck %s --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-1
|
||||
// RUN: %t fail2 | FileCheck %s --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-2
|
||||
// RUN: %t fail3 | FileCheck %s --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-3
|
||||
// RUN: %t fail4 | FileCheck %s --check-prefixes=CHECK,CHECK-FAIL,CHECK-FAIL-4
|
||||
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../include/stdchecked.h"
|
||||
|
||||
void passing_test_1(void);
|
||||
void passing_test_2(array_ptr<int> a : count(1));
|
||||
void passing_test_3(array_ptr<int> a : count(len), int len);
|
||||
|
||||
void failing_test_1(void);
|
||||
void failing_test_2(void);
|
||||
void failing_test_3(array_ptr<int> a : count(0));
|
||||
void failing_test_4(array_ptr<int> a : count(len), int len);
|
||||
|
||||
// Handle an out-of-bounds reference by immediately exiting. This causes
|
||||
// some output to be missing.
|
||||
void handle_error(int err) {
|
||||
_Exit(0);
|
||||
}
|
||||
|
||||
// This signature for main is exactly what we want here,
|
||||
// it also means any uses of argv[i] are checked too!
|
||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||
|
||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
||||
// may change in the future.
|
||||
signal(SIGILL, handle_error);
|
||||
|
||||
// This makes sure output is not buffered for when
|
||||
// we hit errors.
|
||||
int err = setvbuf(stdout, NULL, _IONBF, 0);
|
||||
if (err) {
|
||||
// CHECK-NOT: Error Setting Up Buffering
|
||||
puts("Error Setting Up Buffering");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
// CHECK-NOT: Requires Argument
|
||||
puts("Requires Argument");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int a checked[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
// CHECK: Starting Test
|
||||
puts("Starting Test");
|
||||
|
||||
if (strcmp(argv[1], "pass1") == 0) {
|
||||
// CHECK-PASS-1: Assignable
|
||||
// CHECK-PASS-1: Expected Success
|
||||
passing_test_1();
|
||||
}
|
||||
else if (strcmp(argv[1], "pass2") == 0) {
|
||||
// CHECK-PASS-2: Assignable
|
||||
// CHECK-PASS-2: Expected Success
|
||||
passing_test_2(a);
|
||||
}
|
||||
else if (strcmp(argv[1], "pass3") == 0) {
|
||||
// CHECK-PASS-3: Assignable
|
||||
// CHECK-PASS-3: Expected Success
|
||||
passing_test_3(a, 3);
|
||||
}
|
||||
else if (strcmp(argv[1], "fail1") == 0) {
|
||||
// CHECK-FAIL-1-NOT: Unassignable
|
||||
// CHECK-FAIL-1-NOT: Unexpected Success
|
||||
failing_test_1();
|
||||
}
|
||||
else if (strcmp(argv[1], "fail2") == 0) {
|
||||
// CHECK-FAIL-2-NOT: Unassignable
|
||||
// CHECK-FAIL-2-NOT: Unexpected Success
|
||||
failing_test_2();
|
||||
}
|
||||
else if (strcmp(argv[1], "fail3") == 0) {
|
||||
// CHECK-FAIL-3-NOT: Unassignable
|
||||
// CHECK-FAIL-3-NOT: Unexpected Success
|
||||
failing_test_3(a);
|
||||
}
|
||||
else if (strcmp(argv[1], "fail4") == 0) {
|
||||
// CHECK-FAIL-4-NOT: Unassignable
|
||||
// CHECK-FAIL-4-NOT: Unexpected Success
|
||||
failing_test_4(a, 0);
|
||||
}
|
||||
else {
|
||||
// CHECK-NOT: Unexpected Test Name
|
||||
puts("Unexpected Test Name");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// CHECK-PASS: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-NOT: All Dynamic Checks Passed
|
||||
puts("All Dynamic Checks Passed");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Bounds Describe Valid Pointer, within array, deref is fine
|
||||
void passing_test_1(void) {
|
||||
int a checked[10] = { 0,0,0,0,0,0,0,0,0,0 };
|
||||
array_ptr<int> b : count(5) = &a[2];
|
||||
|
||||
*b = 1;
|
||||
printf("Assignable: %d\n", *b);
|
||||
|
||||
puts("Expected Success");
|
||||
}
|
||||
|
||||
// Bounds Describe valid pointer, within array, deref is fine
|
||||
void passing_test_2(array_ptr<int> a : count(1)) {
|
||||
*a = 2;
|
||||
printf("Assignable: %d\n", *a);
|
||||
|
||||
puts("Expected Success");
|
||||
}
|
||||
|
||||
// Bounds describe valid pointer (assuming len > 0), deref is fine
|
||||
void passing_test_3(array_ptr<int> a : count(len), int len) {
|
||||
assert(len > 0);
|
||||
|
||||
*a = 3;
|
||||
printf("Assignable: %d\n", *a);
|
||||
|
||||
puts("Expected Success");
|
||||
}
|
||||
|
||||
// Bounds describe empty range, no deref
|
||||
void failing_test_1(void) {
|
||||
array_ptr<int> a : bounds(a, a) = 0;
|
||||
|
||||
*a = 1;
|
||||
printf("Unassignable: %d\n", *a);
|
||||
|
||||
puts("Unexpected Success");
|
||||
}
|
||||
|
||||
// Bounds describe empty range (a + 2 > a), no deref
|
||||
void failing_test_2(void) {
|
||||
int a checked[3] = { 0, 0, 0 };
|
||||
array_ptr<int> b : bounds(a + 2, a) = a;
|
||||
|
||||
*b = 2;
|
||||
printf("Unassignable: %d\n", *b);
|
||||
|
||||
puts("Unexpected Success");
|
||||
}
|
||||
|
||||
// Bounds describe empty range, no deref
|
||||
void failing_test_3(array_ptr<int> a : count(0)) {
|
||||
*a = 3;
|
||||
printf("Unassignable: %d\n", *a);
|
||||
|
||||
puts("Unexpected Success");
|
||||
}
|
||||
|
||||
// Bounds describe empty range (assuming len == 0), no deref
|
||||
void failing_test_4(array_ptr<int> a : count(len), int len) {
|
||||
assert(len == 0);
|
||||
|
||||
*a = 4;
|
||||
printf("Unassignable: %d\n", *a);
|
||||
|
||||
puts("Unexpected Success");
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Tests that the Array Subscript Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// This builds the file `write-subscript-check.c` at optimisation level O3, outputting an
|
||||
// executable at %t. We then run this with the same arguments as we run the unoptimised
|
||||
// binary with, and use FileCheck to ensure the output is what we expected, as specified
|
||||
// in `write-subscript-check.c`. This is run as a seperate test so we know if optimisation is
|
||||
// breaking our dynamic checks.
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %S/write-subscript-check.c -o %t -Werror -O3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %S/write-subscript-check.c
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %S/write-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %S/write-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %S/write-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %S/write-subscript-check.c
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %S/write-subscript-check.c
|
||||
// RUN: %t 3 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %S/write-subscript-check.c --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
// Don't run this file
|
||||
return EXIT_FAILURE;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
// Tests that the Array Subscript Operator works with dynamic checks
|
||||
//
|
||||
// The following lines are for the clang automated test suite
|
||||
//
|
||||
// RUN: %clang -fcheckedc-extension %s -o %t -Werror
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 0 | FileCheck %s
|
||||
// RUN: %t 1 2 4 4 1 2 1 1 1 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 2 1 2 2 2 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 0 4 0 3 2 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 1 3 0 1 5 | FileCheck %s
|
||||
// RUN: %t 2 4 8 8 2 -1 2 -1 2 | FileCheck %s
|
||||
// RUN: %t 3 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 5 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 9 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 9 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 -1 | FileCheck %s --check-prefix=CHECK-FAIL-1
|
||||
// RUN: %t 0 0 0 0 3 0 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 2 3 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 9 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 -1 -1 | FileCheck %s --check-prefix=CHECK-FAIL-2
|
||||
// RUN: %t 0 0 0 0 0 0 3 0 0 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 9 0 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 2 2 3 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 0 0 27 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
// RUN: %t 0 0 0 0 0 0 -1 -1 -1 | FileCheck %s --check-prefix=CHECK-FAIL-3
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "../../include/stdchecked.h"
|
||||
|
||||
int a0 checked[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
int ma1 checked[3][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };
|
||||
int ma2 checked[3][3][3] = {
|
||||
{ { 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 } },
|
||||
{ { 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 } },
|
||||
{ { 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 } }
|
||||
};
|
||||
|
||||
array_ptr<int> a1 : count(3) = a0;
|
||||
|
||||
// Handle an out-of-bounds reference by immediately exiting. This causes
|
||||
// some output to be missing.
|
||||
void handle_error(int err) {
|
||||
_Exit(0);
|
||||
}
|
||||
|
||||
// This signature for main is exactly what we want here,
|
||||
// it also means any uses of argv[i] are checked too!
|
||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||
|
||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
||||
// may change in the future.
|
||||
signal(SIGILL, handle_error);
|
||||
|
||||
// Unfortunately, using atoi everywhere below isn't super
|
||||
// great, as it will return 0 if it can't parse, which is a valid,
|
||||
// non-erroring index. This is why we use CHECK-*-NOT to make sure
|
||||
// the tests fail before getting to certain output.
|
||||
|
||||
// This makes sure output is not buffered for when
|
||||
// we hit errors.
|
||||
int err = setvbuf(stdout, NULL, _IONBF, 0);
|
||||
if (err) {
|
||||
// CHECK-NOT: Error Settinug Up Buffering
|
||||
puts("Error Setting Up Buffering");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int idx = 1;
|
||||
|
||||
// CHECK: Starting Test
|
||||
// CHECK-FAIL-1: Starting Test
|
||||
// CHECK-FAIL-2: Starting Test
|
||||
// CHECK-FAIL-3: Starting Test
|
||||
puts("Starting Test");
|
||||
|
||||
array_ptr<int> a2 : count(5) = a0;
|
||||
int a3 checked[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
int i = atoi(argv[idx++]);
|
||||
a1[i] = i;
|
||||
printf("a1[%d] = %d;\n", i, a1[i]);
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
a2[i] = i;
|
||||
printf("a2[%d] = %d;\n", i, a2[i]);
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
a3[i] = i;
|
||||
printf("a3[%d] = %d;\n", i, a3[i]);
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
a0[i] = i;
|
||||
printf("a0[%d] = %d;\n", i, a0[i]);
|
||||
|
||||
// CHECK: 1-Dimensional Checks Passed
|
||||
// CHECK-FAIL-1-NOT: 1-Dimensional Checks Passed
|
||||
// CHECK-FAIL-2: 1-Dimensional Checks Passed
|
||||
// CHECK-FAIL-3: 1-Dimensional Checks Passed
|
||||
puts("1-Dimensional Checks Passed");
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
int j = atoi(argv[idx++]);
|
||||
ma1[i][j] = i + j;
|
||||
printf("ma1[%d][%d] = %d;\n", i, j, ma1[i][j]);
|
||||
|
||||
// CHECK: 2-Dimensional Checks Passed
|
||||
// CHECK-FAIL-1-NOT: 2-Dimensional Checks Passed
|
||||
// CHECK-FAIL-2-NOT: 2-Dimensional Checks Passed
|
||||
// CHECK-FAIL-3: 2-Dimensional Checks Passed
|
||||
puts("2-Dimensional Checks Passed");
|
||||
|
||||
i = atoi(argv[idx++]);
|
||||
j = atoi(argv[idx++]);
|
||||
int k = atoi(argv[idx++]);
|
||||
ma2[i][j][k] = i + j + k;
|
||||
printf("ma2[%d][%d][%d] = %d;\n", i, j, k, ma2[i][j][k]);
|
||||
|
||||
|
||||
// CHECK: 3-Dimensional Checks Passed
|
||||
// CHECK-FAIL-1-NOT: 3-Dimensional Checks Passed
|
||||
// CHECK-FAIL-2-NOT: 3-Dimensional Checks Passed
|
||||
// CHECK-FAIL-3-NOT: 3-Dimensional Checks Passed
|
||||
puts("3-Dimensional Checks Passed");
|
||||
|
||||
// CHECK: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-1-NOT: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-2-NOT: All Dynamic Checks Passed
|
||||
// CHECK-FAIL-3-NOT: All Dynamic Checks Passed
|
||||
puts("All Dynamic Checks Passed");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Загрузка…
Ссылка в новой задаче