forked from OSchip/llvm-project
[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:
parent
c5d628400f
commit
2b9f48afdd
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue