[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.

llvm-svn: 297750
This commit is contained in:
Vedant Kumar 2017-03-14 16:48:29 +00:00
parent c5d628400f
commit 2b9f48afdd
4 changed files with 22 additions and 16 deletions

View File

@ -2938,18 +2938,20 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV,
// Prefer the returns_nonnull attribute if it's present. // Prefer the returns_nonnull attribute if it's present.
SourceLocation AttrLoc; SourceLocation AttrLoc;
SanitizerMask CheckKind; SanitizerMask CheckKind;
SanitizerHandler Handler;
if (RetNNAttr) { if (RetNNAttr) {
assert(!requiresReturnValueNullabilityCheck() && assert(!requiresReturnValueNullabilityCheck() &&
"Cannot check nullability and the nonnull attribute"); "Cannot check nullability and the nonnull attribute");
AttrLoc = RetNNAttr->getLocation(); AttrLoc = RetNNAttr->getLocation();
CheckKind = SanitizerKind::ReturnsNonnullAttribute; CheckKind = SanitizerKind::ReturnsNonnullAttribute;
Handler = SanitizerHandler::NonnullReturn;
} else { } else {
// FIXME: The runtime shouldn't refer to the 'returns_nonnull' attribute.
if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl)) if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl))
if (auto *TSI = DD->getTypeSourceInfo()) if (auto *TSI = DD->getTypeSourceInfo())
if (auto FTL = TSI->getTypeLoc().castAs<FunctionTypeLoc>()) if (auto FTL = TSI->getTypeLoc().castAs<FunctionTypeLoc>())
AttrLoc = FTL.getReturnLoc().findNullabilityLoc(); AttrLoc = FTL.getReturnLoc().findNullabilityLoc();
CheckKind = SanitizerKind::NullabilityReturn; CheckKind = SanitizerKind::NullabilityReturn;
Handler = SanitizerHandler::NullabilityReturn;
} }
SanitizerScope SanScope(this); SanitizerScope SanScope(this);
@ -2971,8 +2973,7 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV,
llvm::Constant *StaticData[] = { llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(AttrLoc), EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(AttrLoc),
}; };
EmitCheck(std::make_pair(Cond, CheckKind), SanitizerHandler::NonnullReturn, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
StaticData, None);
if (requiresReturnValueNullabilityCheck()) if (requiresReturnValueNullabilityCheck())
EmitBlock(NoCheck); EmitBlock(NoCheck);
@ -3314,12 +3315,15 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
SourceLocation AttrLoc; SourceLocation AttrLoc;
SanitizerMask CheckKind; SanitizerMask CheckKind;
SanitizerHandler Handler;
if (NNAttr) { if (NNAttr) {
AttrLoc = NNAttr->getLocation(); AttrLoc = NNAttr->getLocation();
CheckKind = SanitizerKind::NonnullAttribute; CheckKind = SanitizerKind::NonnullAttribute;
Handler = SanitizerHandler::NonnullArg;
} else { } else {
AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc(); AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc();
CheckKind = SanitizerKind::NullabilityArg; CheckKind = SanitizerKind::NullabilityArg;
Handler = SanitizerHandler::NullabilityArg;
} }
SanitizerScope SanScope(this); SanitizerScope SanScope(this);
@ -3331,8 +3335,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc), EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc),
llvm::ConstantInt::get(Int32Ty, ArgNo + 1), llvm::ConstantInt::get(Int32Ty, ArgNo + 1),
}; };
EmitCheck(std::make_pair(Cond, CheckKind), SanitizerHandler::NonnullArg, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
StaticData, None);
} }
void CodeGenFunction::EmitCallArgs( void CodeGenFunction::EmitCallArgs(

View File

@ -685,11 +685,10 @@ void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS,
// hand side must be nonnull. // hand side must be nonnull.
SanitizerScope SanScope(this); SanitizerScope SanScope(this);
llvm::Value *IsNotNull = Builder.CreateIsNotNull(RHS); llvm::Value *IsNotNull = Builder.CreateIsNotNull(RHS);
// FIXME: The runtime shouldn't refer to a 'reference'.
llvm::Constant *StaticData[] = { llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()), EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()),
llvm::ConstantInt::get(Int8Ty, 1), llvm::ConstantInt::get(Int8Ty, 0), //< The LogAlignment info is unused.
llvm::ConstantInt::get(Int8Ty, TCK_ReferenceBinding)}; llvm::ConstantInt::get(Int8Ty, TCK_NonnullAssign)};
EmitCheck({{IsNotNull, SanitizerKind::NullabilityAssign}}, EmitCheck({{IsNotNull, SanitizerKind::NullabilityAssign}},
SanitizerHandler::TypeMismatch, StaticData, RHS); SanitizerHandler::TypeMismatch, StaticData, RHS);
} }

View File

@ -115,6 +115,8 @@ enum TypeEvaluationKind {
SANITIZER_CHECK(MissingReturn, missing_return, 0) \ SANITIZER_CHECK(MissingReturn, missing_return, 0) \
SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \
SANITIZER_CHECK(NegateOverflow, negate_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(NonnullArg, nonnull_arg, 0) \
SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \ SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \
SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \
@ -2290,7 +2292,9 @@ public:
TCK_Upcast, TCK_Upcast,
/// Checking the operand of a cast to a virtual base object. Must be an /// Checking the operand of a cast to a virtual base object. Must be an
/// object within its lifetime. /// 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, /// \brief Whether any type-checking sanitizers are enabled. If \c false,

View File

@ -20,7 +20,7 @@ int *_Nonnull nonnull_retval1(int *p) {
// CHECK: [[NULL]]: // CHECK: [[NULL]]:
// CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !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; return p;
// CHECK: [[NONULL]]: // CHECK: [[NONULL]]:
// CHECK-NEXT: ret i32* // CHECK-NEXT: ret i32*
@ -34,7 +34,7 @@ void nonnull_arg(int *_Nonnull p) {}
void call_func_with_nonnull_arg(int *_Nonnull p) { void call_func_with_nonnull_arg(int *_Nonnull p) {
// CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !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); nonnull_arg(p);
} }
@ -108,7 +108,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
// CHECK: [[NULL]]: // CHECK: [[NULL]]:
// CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !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; return arg1;
// CHECK: [[NONULL]]: // CHECK: [[NONULL]]:
// CHECK-NEXT: ret i32* // CHECK-NEXT: ret i32*
@ -129,7 +129,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
// CHECK: [[NULL]]: // CHECK: [[NULL]]:
// CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
// CHECK: call void @__ubsan_handle_nonnull_return{{.*}} // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
return arg1; return arg1;
// CHECK: [[NONULL]]: // CHECK: [[NONULL]]:
// CHECK-NEXT: ret i32* // CHECK-NEXT: ret i32*
@ -143,7 +143,7 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
// CHECK: [[NULL]]: // CHECK: [[NULL]]:
// CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
// CHECK: call void @__ubsan_handle_nonnull_return{{.*}} // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
return arg1; return arg1;
// CHECK: [[NONULL]]: // CHECK: [[NONULL]]:
// CHECK-NEXT: ret i32* // CHECK-NEXT: ret i32*
@ -154,13 +154,13 @@ int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
void call_A(A *a, int *p) { void call_A(A *a, int *p) {
// CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !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]]) // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P1]])
[a objc_method: p]; [a objc_method: p];
// CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize
// CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !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]]) // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P2]])
[A objc_clsmethod: p]; [A objc_clsmethod: p];
} }