mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 23:36:05 +00:00
[ubsan] Factor out logic to emit a range check. NFC.
This is a readability improvement, but it will also help prep an upcoming patch to detect UB loads from bitfields. llvm-svn: 296374
This commit is contained in:
parent
aaf5191364
commit
5a97265351
@ -1301,6 +1301,46 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
|
||||
return MDHelper.createRange(Min, End);
|
||||
}
|
||||
|
||||
bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
|
||||
SourceLocation Loc) {
|
||||
bool HasBoolCheck = SanOpts.has(SanitizerKind::Bool);
|
||||
bool HasEnumCheck = SanOpts.has(SanitizerKind::Enum);
|
||||
if (!HasBoolCheck && !HasEnumCheck)
|
||||
return false;
|
||||
|
||||
bool IsBool = hasBooleanRepresentation(Ty) ||
|
||||
NSAPI(CGM.getContext()).isObjCBOOLType(Ty);
|
||||
bool NeedsBoolCheck = HasBoolCheck && IsBool;
|
||||
bool NeedsEnumCheck = HasEnumCheck && Ty->getAs<EnumType>();
|
||||
if (!NeedsBoolCheck && !NeedsEnumCheck)
|
||||
return false;
|
||||
|
||||
llvm::APInt Min, End;
|
||||
if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool))
|
||||
return true;
|
||||
|
||||
SanitizerScope SanScope(this);
|
||||
llvm::Value *Check;
|
||||
--End;
|
||||
if (!Min) {
|
||||
Check = Builder.CreateICmpULE(
|
||||
Value, llvm::ConstantInt::get(getLLVMContext(), End));
|
||||
} else {
|
||||
llvm::Value *Upper = Builder.CreateICmpSLE(
|
||||
Value, llvm::ConstantInt::get(getLLVMContext(), End));
|
||||
llvm::Value *Lower = Builder.CreateICmpSGE(
|
||||
Value, llvm::ConstantInt::get(getLLVMContext(), Min));
|
||||
Check = Builder.CreateAnd(Upper, Lower);
|
||||
}
|
||||
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc),
|
||||
EmitCheckTypeDescriptor(Ty)};
|
||||
SanitizerMask Kind =
|
||||
NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
|
||||
EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue,
|
||||
StaticArgs, EmitCheckValue(Value));
|
||||
return true;
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
|
||||
QualType Ty,
|
||||
SourceLocation Loc,
|
||||
@ -1353,35 +1393,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
|
||||
false /*ConvertTypeToTag*/);
|
||||
}
|
||||
|
||||
bool IsBool = hasBooleanRepresentation(Ty) ||
|
||||
NSAPI(CGM.getContext()).isObjCBOOLType(Ty);
|
||||
bool NeedsBoolCheck = SanOpts.has(SanitizerKind::Bool) && IsBool;
|
||||
bool NeedsEnumCheck =
|
||||
SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>();
|
||||
if (NeedsBoolCheck || NeedsEnumCheck) {
|
||||
SanitizerScope SanScope(this);
|
||||
llvm::APInt Min, End;
|
||||
if (getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool)) {
|
||||
--End;
|
||||
llvm::Value *Check;
|
||||
if (!Min)
|
||||
Check = Builder.CreateICmpULE(
|
||||
Load, llvm::ConstantInt::get(getLLVMContext(), End));
|
||||
else {
|
||||
llvm::Value *Upper = Builder.CreateICmpSLE(
|
||||
Load, llvm::ConstantInt::get(getLLVMContext(), End));
|
||||
llvm::Value *Lower = Builder.CreateICmpSGE(
|
||||
Load, llvm::ConstantInt::get(getLLVMContext(), Min));
|
||||
Check = Builder.CreateAnd(Upper, Lower);
|
||||
}
|
||||
llvm::Constant *StaticArgs[] = {
|
||||
EmitCheckSourceLocation(Loc),
|
||||
EmitCheckTypeDescriptor(Ty)
|
||||
};
|
||||
SanitizerMask Kind = NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
|
||||
EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue,
|
||||
StaticArgs, EmitCheckValue(Load));
|
||||
}
|
||||
if (EmitScalarRangeCheck(Load, Ty, Loc)) {
|
||||
// In order to prevent the optimizer from throwing away the check, don't
|
||||
// attach range metadata to the load.
|
||||
} else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
|
||||
if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
|
||||
Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
|
||||
|
@ -2866,6 +2866,13 @@ public:
|
||||
/// representation to its value representation.
|
||||
llvm::Value *EmitFromMemory(llvm::Value *Value, QualType Ty);
|
||||
|
||||
/// Check if the scalar \p Value is within the valid range for the given
|
||||
/// type \p Ty.
|
||||
///
|
||||
/// Returns true if a check is needed (even if the range is unknown).
|
||||
bool EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
|
||||
SourceLocation Loc);
|
||||
|
||||
/// EmitLoadOfScalar - Load a scalar value from an address, taking
|
||||
/// care to appropriately convert from the memory representation to
|
||||
/// the LLVM value representation.
|
||||
|
Loading…
x
Reference in New Issue
Block a user