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:
Sam Elliott 2017-03-08 15:39:20 -08:00 коммит произвёл GitHub
Родитель c2cf77e4ca
Коммит ec6d087122
19 изменённых файлов: 662 добавлений и 104 удалений

Просмотреть файл

@ -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;
}