1 // REQUIRES: x86-registered-target 2 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=0 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0 3 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=0 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0,CXX,CXX-STRICT-0 4 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=1 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1 5 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=1 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1,CXX 6 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2 7 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2,CXX 8 // Before flexible array member was added to C99, many projects use a 9 // one-element array as the last member of a structure as an alternative. 10 // E.g. https://github.com/python/cpython/issues/84301 11 // Suppress such errors with -fstrict-flex-arrays=0. 12 struct One { 13 int a[1]; 14 }; 15 struct Two { 16 int a[2]; 17 }; 18 struct Three { 19 int a[3]; 20 }; 21 22 // CHECK-LABEL: define {{.*}} @{{.*}}test_one{{.*}}( 23 int test_one(struct One *p, int i) { 24 // CHECK-STRICT-0-NOT: @__ubsan 25 // CHECK-STRICT-1-NOT: @__ubsan 26 // CHECK-STRICT-2: call void @__ubsan_handle_out_of_bounds_abort( 27 return p->a[i] + (p->a)[i]; 28 } 29 30 // CHECK-LABEL: define {{.*}} @{{.*}}test_two{{.*}}( 31 int test_two(struct Two *p, int i) { 32 // CHECK-STRICT-0: call void @__ubsan_handle_out_of_bounds_abort( 33 // CHECK-STRICT-1: call void @__ubsan_handle_out_of_bounds_abort( 34 // CHECK-STRICT-2: call void @__ubsan_handle_out_of_bounds_abort( 35 return p->a[i] + (p->a)[i]; 36 } 37 38 // CHECK-LABEL: define {{.*}} @{{.*}}test_three{{.*}}( 39 int test_three(struct Three *p, int i) { 40 // CHECK-STRICT-0: call void @__ubsan_handle_out_of_bounds_abort( 41 // CHECK-STRICT-1: call void @__ubsan_handle_out_of_bounds_abort( 42 // CHECK-STRICT-2: call void @__ubsan_handle_out_of_bounds_abort( 43 return p->a[i] + (p->a)[i]; 44 } 45 46 #define FLEXIBLE 1 47 struct Macro { 48 int a[FLEXIBLE]; 49 }; 50 51 // CHECK-LABEL: define {{.*}} @{{.*}}test_macro{{.*}}( 52 int test_macro(struct Macro *p, int i) { 53 // CHECK-STRICT-0-NOT: @__ubsan 54 return p->a[i] + (p->a)[i]; 55 } 56 57 #if defined __cplusplus 58 59 struct Base { 60 int b; 61 }; 62 struct NoStandardLayout : Base { 63 int a[1]; 64 }; 65 66 // CXX-LABEL: define {{.*}} @{{.*}}test_nostandardlayout{{.*}}( 67 int test_nostandardlayout(NoStandardLayout *p, int i) { 68 // CXX-STRICT-0-NOT: @__ubsan 69 return p->a[i] + (p->a)[i]; 70 } 71 72 template<int N> struct Template { 73 int a[N]; 74 }; 75 76 // CXX-LABEL: define {{.*}} @{{.*}}test_template{{.*}}( 77 int test_template(Template<1> *p, int i) { 78 // CXX-STRICT-0-NOT: @__ubsan 79 return p->a[i] + (p->a)[i]; 80 } 81 82 #endif 83