r301482 - [ubsan] nullability-assign: Check assignments into C++ structs

Vedant Kumar via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 26 14:55:18 PDT 2017


Author: vedantk
Date: Wed Apr 26 16:55:17 2017
New Revision: 301482

URL: http://llvm.org/viewvc/llvm-project?rev=301482&view=rev
Log:
[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.

Added:
    cfe/trunk/test/CodeGenCXX/ubsan-nullability-assign.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/test/CodeGenObjC/ubsan-nullability.m

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=301482&r1=301481&r2=301482&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Wed Apr 26 16:55:17 2017
@@ -4065,6 +4065,8 @@ LValue CodeGenFunction::EmitBinaryOperat
 
     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;
   }

Added: cfe/trunk/test/CodeGenCXX/ubsan-nullability-assign.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-nullability-assign.cpp?rev=301482&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ubsan-nullability-assign.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/ubsan-nullability-assign.cpp Wed Apr 26 16:55:17 2017
@@ -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
+}

Modified: cfe/trunk/test/CodeGenObjC/ubsan-nullability.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/ubsan-nullability.m?rev=301482&r1=301481&r2=301482&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/ubsan-nullability.m (original)
+++ cfe/trunk/test/CodeGenObjC/ubsan-nullability.m Wed Apr 26 16:55:17 2017
@@ -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 *_No
   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 *_Nonn
 }
 @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;
 }




More information about the cfe-commits mailing list