diff options
| author | Vedant Kumar <vsk@apple.com> | 2017-04-26 21:55:17 +0000 |
|---|---|---|
| committer | Vedant Kumar <vsk@apple.com> | 2017-04-26 21:55:17 +0000 |
| commit | 6b22dda5a3909f46862ec001110b5d4671bbf142 (patch) | |
| tree | cb6d69b78291b28f697fe78155d7d57112803ee7 | |
| parent | e6d2bebb25f2c1a1ffb1884b11df37ff50a33c49 (diff) | |
| download | bcm5719-llvm-6b22dda5a3909f46862ec001110b5d4671bbf142.tar.gz bcm5719-llvm-6b22dda5a3909f46862ec001110b5d4671bbf142.zip | |
[ubsan] nullability-assign: Check assignments into C++ structs
Fix the nullability-assign check so that it can handle assignments into
C++ structs. Previously, such assignments were not instrumented.
Testing: check-clang, check-ubsan, enabling the existing test in ObjC++
mode, and building some Apple frameworks with -fsanitize=nullability.
llvm-svn: 301482
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/ubsan-nullability-assign.cpp | 35 | ||||
| -rw-r--r-- | clang/test/CodeGenObjC/ubsan-nullability.m | 44 |
3 files changed, 61 insertions, 20 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d0aacf65428..863b4380da4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4065,6 +4065,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { RValue RV = EmitAnyExpr(E->getRHS()); LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store); + if (RV.isScalar()) + EmitNullabilityCheck(LV, RV.getScalarVal(), E->getExprLoc()); EmitStoreThroughLValue(RV, LV); return LV; } diff --git a/clang/test/CodeGenCXX/ubsan-nullability-assign.cpp b/clang/test/CodeGenCXX/ubsan-nullability-assign.cpp new file mode 100644 index 00000000000..3f85c88d6e7 --- /dev/null +++ b/clang/test/CodeGenCXX/ubsan-nullability-assign.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=nullability-assign | FileCheck %s + +struct S1 { + int *_Nonnull p; +}; + +struct S2 { + S1 s1; +}; + +union U1 { + S1 s1; + S2 s2; +}; + +// CHECK-LABEL: define void @{{.*}}f1 +void f1(int *p) { + U1 u; + + // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}} !nosanitize + // CHECK: store + u.s1.p = p; + + // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize + // CHECK: call void @__ubsan_handle_type_mismatch{{.*}} !nosanitize + // CHECK: store + u.s2.s1.p = p; + + // CHECK-NOT: __ubsan_handle_type_mismatch + // CHECK-NOT: store + // CHECK: ret void +} diff --git a/clang/test/CodeGenObjC/ubsan-nullability.m b/clang/test/CodeGenObjC/ubsan-nullability.m index 457f0713634..7f53ea6292e 100644 --- a/clang/test/CodeGenObjC/ubsan-nullability.m +++ b/clang/test/CodeGenObjC/ubsan-nullability.m @@ -1,19 +1,22 @@ // REQUIRES: asserts // RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s +// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s // CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 109, i32 1 {{.*}} i32 100, i32 6 // CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23 // CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9 // CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10 -// CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 505, i32 10 +// CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 506, i32 10 // CHECK: [[NONNULL_INIT1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 604, i32 25 // CHECK: [[NONNULL_INIT2_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 26 // CHECK: [[NONNULL_INIT2_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 29 // CHECK: [[NONNULL_RV_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 817, i32 1 {{.*}} i32 800, i32 6 #define NULL ((void *)0) +#define INULL ((int *)NULL) +#define INNULL ((int *_Nonnull)NULL) -// CHECK-LABEL: define i32* @nonnull_retval1 +// CHECK-LABEL: define i32* @{{.*}}nonnull_retval1 #line 100 int *_Nonnull nonnull_retval1(int *p) { // CHECK: br i1 true, label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize @@ -29,7 +32,7 @@ int *_Nonnull nonnull_retval1(int *p) { #line 190 void nonnull_arg(int *_Nonnull p) {} -// CHECK-LABEL: define void @call_func_with_nonnull_arg +// CHECK-LABEL: define void @{{.*}}call_func_with_nonnull_arg #line 200 void call_func_with_nonnull_arg(int *_Nonnull p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize @@ -38,7 +41,7 @@ void call_func_with_nonnull_arg(int *_Nonnull p) { nonnull_arg(p); } -// CHECK-LABEL: define void @nonnull_assign1 +// CHECK-LABEL: define void @{{.*}}nonnull_assign1 #line 300 void nonnull_assign1(int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize @@ -48,7 +51,7 @@ void nonnull_assign1(int *p) { local = p; } -// CHECK-LABEL: define void @nonnull_assign2 +// CHECK-LABEL: define void @{{.*}}nonnull_assign2 #line 400 void nonnull_assign2(int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize @@ -62,17 +65,18 @@ struct S1 { int *_Nonnull mptr; }; -// CHECK-LABEL: define void @nonnull_assign3 +// CHECK-LABEL: define void @{{.*}}nonnull_assign3 #line 500 void nonnull_assign3(int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]] + // CHECK-NOT: call void @__ubsan_handle_type_mismatch struct S1 s; s.mptr = p; } -// CHECK-LABEL: define void @nonnull_init1 +// CHECK-LABEL: define void @{{.*}}nonnull_init1 #line 600 void nonnull_init1(int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize @@ -81,7 +85,7 @@ void nonnull_init1(int *p) { int *_Nonnull local = p; } -// CHECK-LABEL: define void @nonnull_init2 +// CHECK-LABEL: define void @{{.*}}nonnull_init2 #line 700 void nonnull_init2(int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize @@ -93,7 +97,7 @@ void nonnull_init2(int *p) { int *_Nonnull arr[] = {p, p}; } -// CHECK-LABEL: define i32* @nonnull_retval2 +// CHECK-LABEL: define i32* @{{.*}}nonnull_retval2 #line 800 int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. int *_Nonnull arg2, //< Test this. @@ -150,7 +154,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. } @end -// CHECK-LABEL: define void @call_A +// CHECK-LABEL: define void @{{.*}}call_A void call_A(A *a, int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize @@ -168,15 +172,15 @@ void call_A(A *a, int *p) { void dont_crash(int *_Nonnull p, ...) {} int main() { - nonnull_retval1(NULL); - nonnull_retval2(NULL, NULL, NULL, NULL, 0, 0, 0, 0); - call_func_with_nonnull_arg(NULL); - nonnull_assign1(NULL); - nonnull_assign2(NULL); - nonnull_assign3(NULL); - nonnull_init1(NULL); - nonnull_init2(NULL); - call_A(NULL, NULL); - dont_crash(NULL, NULL); + nonnull_retval1(INULL); + nonnull_retval2(INNULL, INNULL, INULL, (int *_Nullable)NULL, 0, 0, 0, 0); + call_func_with_nonnull_arg(INNULL); + nonnull_assign1(INULL); + nonnull_assign2(INULL); + nonnull_assign3(INULL); + nonnull_init1(INULL); + nonnull_init2(INULL); + call_A((A *)NULL, INULL); + dont_crash(INNULL, NULL); return 0; } |

