Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 61 additions & 36 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,43 +1235,65 @@ llvm::Value *CodeGenFunction::EmitLoadOfCountedByField(
return nullptr;
}

void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
llvm::Value *Index, QualType IndexType,
void CodeGenFunction::EmitBoundsCheck(const Expr *ArrayExpr,
const Expr *ArrayExprBase,
llvm::Value *IndexVal, QualType IndexType,
bool Accessed) {
assert(SanOpts.has(SanitizerKind::ArrayBounds) &&
"should not be called unless adding bounds checks");
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
QualType IndexedType;
llvm::Value *Bound =
getArrayIndexingBound(*this, Base, IndexedType, StrictFlexArraysLevel);
QualType ArrayExprBaseType;
llvm::Value *BoundsVal = getArrayIndexingBound(
*this, ArrayExprBase, ArrayExprBaseType, StrictFlexArraysLevel);

EmitBoundsCheckImpl(E, Bound, Index, IndexType, IndexedType, Accessed);
EmitBoundsCheckImpl(ArrayExpr, ArrayExprBaseType, IndexVal, IndexType,
BoundsVal, getContext().getSizeType(), Accessed);
}

void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
llvm::Value *Index,
void CodeGenFunction::EmitBoundsCheckImpl(const Expr *ArrayExpr,
QualType ArrayBaseType,
llvm::Value *IndexVal,
QualType IndexType,
QualType IndexedType, bool Accessed) {
if (!Bound)
llvm::Value *BoundsVal,
QualType BoundsType, bool Accessed) {
if (!BoundsVal)
return;

auto CheckKind = SanitizerKind::SO_ArrayBounds;
auto CheckHandler = SanitizerHandler::OutOfBounds;
SanitizerDebugLocation SanScope(this, {CheckKind}, CheckHandler);

// All hail the C implicit type conversion rules!!!
bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType();
llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned);
llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false);
bool BoundsSigned = BoundsType->isSignedIntegerOrEnumerationType();

const ASTContext &Ctx = getContext();
llvm::Type *Ty = ConvertType(
Ctx.getTypeSize(IndexType) >= Ctx.getTypeSize(BoundsType) ? IndexType
: BoundsType);

llvm::Value *IndexInst = Builder.CreateIntCast(IndexVal, Ty, IndexSigned);
llvm::Value *BoundsInst = Builder.CreateIntCast(BoundsVal, Ty, false);

llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(E->getExprLoc()),
EmitCheckTypeDescriptor(IndexedType),
EmitCheckTypeDescriptor(IndexType)
EmitCheckSourceLocation(ArrayExpr->getExprLoc()),
EmitCheckTypeDescriptor(ArrayBaseType),
EmitCheckTypeDescriptor(IndexType),
};
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
: Builder.CreateICmpULE(IndexVal, BoundVal);
EmitCheck(std::make_pair(Check, CheckKind), CheckHandler, StaticData, Index);

llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexInst, BoundsInst)
: Builder.CreateICmpULE(IndexInst, BoundsInst);

if (BoundsSigned) {
// Don't allow a negative bounds.
llvm::Value *Cmp = Builder.CreateICmpSGT(
BoundsVal, llvm::ConstantInt::get(BoundsVal->getType(), 0));
Check = Builder.CreateAnd(Cmp, Check);
}

EmitCheck(std::make_pair(Check, CheckKind), CheckHandler, StaticData,
IndexInst);
}

llvm::MDNode *CodeGenFunction::buildAllocToken(QualType AllocType) {
Expand Down Expand Up @@ -4608,9 +4630,10 @@ static std::optional<int64_t> getOffsetDifferenceInBits(CodeGenFunction &CGF,
/// i.e. "a.b.count", so we shouldn't need the full force of EmitLValue or
/// similar to emit the correct GEP.
void CodeGenFunction::EmitCountedByBoundsChecking(
const Expr *E, llvm::Value *Idx, Address Addr, QualType IdxTy,
QualType ArrayTy, bool Accessed, bool FlexibleArray) {
const auto *ME = dyn_cast<MemberExpr>(E->IgnoreImpCasts());
const Expr *ArrayExpr, QualType ArrayType, Address ArrayInst,
QualType IndexType, llvm::Value *IndexVal, bool Accessed,
bool FlexibleArray) {
const auto *ME = dyn_cast<MemberExpr>(ArrayExpr->IgnoreImpCasts());
if (!ME || !ME->getMemberDecl()->getType()->isCountAttributedType())
return;

Expand All @@ -4627,11 +4650,11 @@ void CodeGenFunction::EmitCountedByBoundsChecking(

if (std::optional<int64_t> Diff =
getOffsetDifferenceInBits(*this, CountFD, FD)) {
if (!Addr.isValid()) {
if (!ArrayInst.isValid()) {
// An invalid Address indicates we're checking a pointer array access.
// Emit the checked L-Value here.
LValue LV = EmitCheckedLValue(E, TCK_MemberAccess);
Addr = LV.getAddress();
LValue LV = EmitCheckedLValue(ArrayExpr, TCK_MemberAccess);
ArrayInst = LV.getAddress();
}

// FIXME: The 'static_cast' is necessary, otherwise the result turns into a
Expand All @@ -4640,17 +4663,19 @@ void CodeGenFunction::EmitCountedByBoundsChecking(

// Create a GEP with the byte offset between the counted object and the
// count and use that to load the count value.
Addr = Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Int8PtrTy, Int8Ty);
ArrayInst = Builder.CreatePointerBitCastOrAddrSpaceCast(ArrayInst,
Int8PtrTy, Int8Ty);

llvm::Type *CountTy = ConvertType(CountFD->getType());
llvm::Value *Res =
Builder.CreateInBoundsGEP(Int8Ty, Addr.emitRawPointer(*this),
llvm::Type *BoundsType = ConvertType(CountFD->getType());
llvm::Value *BoundsVal =
Builder.CreateInBoundsGEP(Int8Ty, ArrayInst.emitRawPointer(*this),
Builder.getInt32(*Diff), ".counted_by.gep");
Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(),
".counted_by.load");
BoundsVal = Builder.CreateAlignedLoad(BoundsType, BoundsVal, getIntAlign(),
".counted_by.load");

// Now emit the bounds checking.
EmitBoundsCheckImpl(E, Res, Idx, IdxTy, ArrayTy, Accessed);
EmitBoundsCheckImpl(ArrayExpr, ArrayType, IndexVal, IndexType, BoundsVal,
CountFD->getType(), Accessed);
}
}

Expand Down Expand Up @@ -4796,9 +4821,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
auto *Idx = EmitIdxAfterBase(/*Promote*/true);

if (SanOpts.has(SanitizerKind::ArrayBounds))
EmitCountedByBoundsChecking(Array, Idx, ArrayLV.getAddress(),
E->getIdx()->getType(), Array->getType(),
Accessed, /*FlexibleArray=*/true);
EmitCountedByBoundsChecking(Array, Array->getType(), ArrayLV.getAddress(),
E->getIdx()->getType(), Idx, Accessed,
/*FlexibleArray=*/true);

// Propagate the alignment from the array itself to the result.
QualType arrayType = Array->getType();
Expand Down Expand Up @@ -4850,8 +4875,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,

if (const auto *CE = dyn_cast_if_present<CastExpr>(Base);
CE && CE->getCastKind() == CK_LValueToRValue)
EmitCountedByBoundsChecking(CE, Idx, Address::invalid(),
E->getIdx()->getType(), ptrType, Accessed,
EmitCountedByBoundsChecking(CE, ptrType, Address::invalid(),
E->getIdx()->getType(), Idx, Accessed,
/*FlexibleArray=*/false);
}
}
Expand Down
17 changes: 9 additions & 8 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3339,11 +3339,12 @@ class CodeGenFunction : public CodeGenTypeCache {
/// Emit a check that \p Base points into an array object, which
/// we can access at index \p Index. \p Accessed should be \c false if we
/// this expression is used as an lvalue, for instance in "&Arr[Idx]".
void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index,
QualType IndexType, bool Accessed);
void EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
llvm::Value *Index, QualType IndexType,
QualType IndexedType, bool Accessed);
void EmitBoundsCheck(const Expr *ArrayExpr, const Expr *ArrayExprBase,
llvm::Value *Index, QualType IndexType, bool Accessed);
void EmitBoundsCheckImpl(const Expr *ArrayExpr, QualType ArrayBaseType,
llvm::Value *IndexVal, QualType IndexType,
llvm::Value *BoundsVal, QualType BoundsType,
bool Accessed);

/// Returns debug info, with additional annotation if
/// CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo[Ordinal] is enabled for
Expand Down Expand Up @@ -3372,9 +3373,9 @@ class CodeGenFunction : public CodeGenTypeCache {

// Emit bounds checking for flexible array and pointer members with the
// counted_by attribute.
void EmitCountedByBoundsChecking(const Expr *E, llvm::Value *Idx,
Address Addr, QualType IdxTy,
QualType ArrayTy, bool Accessed,
void EmitCountedByBoundsChecking(const Expr *ArrayExpr, QualType ArrayType,
Address ArrayInst, QualType IndexType,
llvm::Value *IndexVal, bool Accessed,
bool FlexibleArray);

llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
Expand Down
Loading