From 62ace80238719ca137bcd15272c606ea18d33e88 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 14 Mar 2017 16:48:29 +0000 Subject: [PATCH] [ubsan] Use the nicer nullability diagnostic handlers This is a follow-up to r297700 (Add a nullability sanitizer). It addresses some FIXME's re: using nullability-specific diagnostic handlers from compiler-rt, now that the necessary handlers exist. check-ubsan test updates to follow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@297750 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 13 ++++++++----- lib/CodeGen/CGDecl.cpp | 5 ++--- lib/CodeGen/CodeGenFunction.h | 6 +++++- test/CodeGenObjC/ubsan-nullability.m | 14 +++++++------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 5f069bfe46..34ac95eadc 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -2938,18 +2938,20 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV, // Prefer the returns_nonnull attribute if it's present. SourceLocation AttrLoc; SanitizerMask CheckKind; + SanitizerHandler Handler; if (RetNNAttr) { assert(!requiresReturnValueNullabilityCheck() && "Cannot check nullability and the nonnull attribute"); AttrLoc = RetNNAttr->getLocation(); CheckKind = SanitizerKind::ReturnsNonnullAttribute; + Handler = SanitizerHandler::NonnullReturn; } else { - // FIXME: The runtime shouldn't refer to the 'returns_nonnull' attribute. if (auto *DD = dyn_cast(CurCodeDecl)) if (auto *TSI = DD->getTypeSourceInfo()) if (auto FTL = TSI->getTypeLoc().castAs()) AttrLoc = FTL.getReturnLoc().findNullabilityLoc(); CheckKind = SanitizerKind::NullabilityReturn; + Handler = SanitizerHandler::NullabilityReturn; } SanitizerScope SanScope(this); @@ -2971,8 +2973,7 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV, llvm::Constant *StaticData[] = { EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(AttrLoc), }; - EmitCheck(std::make_pair(Cond, CheckKind), SanitizerHandler::NonnullReturn, - StaticData, None); + EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None); if (requiresReturnValueNullabilityCheck()) EmitBlock(NoCheck); @@ -3314,12 +3315,15 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation AttrLoc; SanitizerMask CheckKind; + SanitizerHandler Handler; if (NNAttr) { AttrLoc = NNAttr->getLocation(); CheckKind = SanitizerKind::NonnullAttribute; + Handler = SanitizerHandler::NonnullArg; } else { AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc(); CheckKind = SanitizerKind::NullabilityArg; + Handler = SanitizerHandler::NullabilityArg; } SanitizerScope SanScope(this); @@ -3331,8 +3335,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc), llvm::ConstantInt::get(Int32Ty, ArgNo + 1), }; - EmitCheck(std::make_pair(Cond, CheckKind), SanitizerHandler::NonnullArg, - StaticData, None); + EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None); } void CodeGenFunction::EmitCallArgs( diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index cfadce5c22..edfc674137 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -685,11 +685,10 @@ void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, // hand side must be nonnull. SanitizerScope SanScope(this); llvm::Value *IsNotNull = Builder.CreateIsNotNull(RHS); - // FIXME: The runtime shouldn't refer to a 'reference'. llvm::Constant *StaticData[] = { EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()), - llvm::ConstantInt::get(Int8Ty, 1), - llvm::ConstantInt::get(Int8Ty, TCK_ReferenceBinding)}; + llvm::ConstantInt::get(Int8Ty, 0), //< The LogAlignment info is unused. + llvm::ConstantInt::get(Int8Ty, TCK_NonnullAssign)}; EmitCheck({{IsNotNull, SanitizerKind::NullabilityAssign}}, SanitizerHandler::TypeMismatch, StaticData, RHS); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 2db8a18cef..7e99bdb73c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -115,6 +115,8 @@ enum TypeEvaluationKind { SANITIZER_CHECK(MissingReturn, missing_return, 0) \ SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \ + SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \ + SANITIZER_CHECK(NullabilityReturn, nullability_return, 0) \ SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \ SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ @@ -2290,7 +2292,9 @@ public: TCK_Upcast, /// Checking the operand of a cast to a virtual base object. Must be an /// object within its lifetime. - TCK_UpcastToVirtualBase + TCK_UpcastToVirtualBase, + /// Checking the value assigned to a _Nonnull pointer. Must not be null. + TCK_NonnullAssign }; /// \brief Whether any type-checking sanitizers are enabled. If \c false, diff --git a/test/CodeGenObjC/ubsan-nullability.m b/test/CodeGenObjC/ubsan-nullability.m index d72b774ec7..457f071363 100644 --- a/test/CodeGenObjC/ubsan-nullability.m +++ b/test/CodeGenObjC/ubsan-nullability.m @@ -20,7 +20,7 @@ int *_Nonnull nonnull_retval1(int *p) { // CHECK: [[NULL]]: // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_return{{.*}}[[NONNULL_RV_LOC1]] + // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]] return p; // CHECK: [[NONULL]]: // CHECK-NEXT: ret i32* @@ -34,7 +34,7 @@ void nonnull_arg(int *_Nonnull p) {} void call_func_with_nonnull_arg(int *_Nonnull p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_arg{{.*}}[[NONNULL_ARG_LOC]] + // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]] nonnull_arg(p); } @@ -108,7 +108,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. // CHECK: [[NULL]]: // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_return{{.*}}[[NONNULL_RV_LOC2]] + // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]] return arg1; // CHECK: [[NONULL]]: // CHECK-NEXT: ret i32* @@ -129,7 +129,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. // CHECK: [[NULL]]: // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_return{{.*}} + // CHECK: call void @__ubsan_handle_nullability_return{{.*}} return arg1; // CHECK: [[NONULL]]: // CHECK-NEXT: ret i32* @@ -143,7 +143,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. // CHECK: [[NULL]]: // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_return{{.*}} + // CHECK: call void @__ubsan_handle_nullability_return{{.*}} return arg1; // CHECK: [[NONULL]]: // CHECK-NEXT: ret i32* @@ -154,13 +154,13 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. void call_A(A *a, int *p) { // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_arg{{.*}} !nosanitize + // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P1]]) [a objc_method: p]; // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize - // CHECK: call void @__ubsan_handle_nonnull_arg{{.*}} !nosanitize + // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P2]]) [A objc_clsmethod: p]; } -- 2.40.0