summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-01-23 03:37:29 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-01-23 03:37:29 +0000
commitcfa79b27b5c50c0f698176355b9f3249036c267e (patch)
tree70777ab9e9edf970619c545490fef61ef0778c0d /clang/lib
parent59d99731467654bd488d54eaa44855c5b5a0d8c0 (diff)
downloadbcm5719-llvm-cfa79b27b5c50c0f698176355b9f3249036c267e.tar.gz
bcm5719-llvm-cfa79b27b5c50c0f698176355b9f3249036c267e.zip
[ubsan] Check the correct size when sanitizing array new.
We previously forgot to multiply the element size by the array bound. llvm-svn: 351924
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp39
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp12
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h6
3 files changed, 36 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index c8df3a4f646..be30e8215ad 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -652,7 +652,8 @@ bool CodeGenFunction::sanitizePerformTypeCheck() const {
void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Ptr, QualType Ty,
CharUnits Alignment,
- SanitizerSet SkippedChecks) {
+ SanitizerSet SkippedChecks,
+ llvm::Value *ArraySize) {
if (!sanitizePerformTypeCheck())
return;
@@ -710,21 +711,27 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if (SanOpts.has(SanitizerKind::ObjectSize) &&
!SkippedChecks.has(SanitizerKind::ObjectSize) &&
!Ty->isIncompleteType()) {
- uint64_t Size = getContext().getTypeSizeInChars(Ty).getQuantity();
-
- // The glvalue must refer to a large enough storage region.
- // FIXME: If Address Sanitizer is enabled, insert dynamic instrumentation
- // to check this.
- // FIXME: Get object address space
- llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy };
- llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
- llvm::Value *Min = Builder.getFalse();
- llvm::Value *NullIsUnknown = Builder.getFalse();
- llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy);
- llvm::Value *LargeEnough = Builder.CreateICmpUGE(
- Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown}),
- llvm::ConstantInt::get(IntPtrTy, Size));
- Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
+ uint64_t TySize = getContext().getTypeSizeInChars(Ty).getQuantity();
+ llvm::Value *Size = llvm::ConstantInt::get(IntPtrTy, TySize);
+ if (ArraySize)
+ Size = Builder.CreateMul(Size, ArraySize);
+
+ // Degenerate case: new X[0] does not need an objectsize check.
+ llvm::Constant *ConstantSize = dyn_cast<llvm::Constant>(Size);
+ if (!ConstantSize || !ConstantSize->isNullValue()) {
+ // The glvalue must refer to a large enough storage region.
+ // FIXME: If Address Sanitizer is enabled, insert dynamic instrumentation
+ // to check this.
+ // FIXME: Get object address space
+ llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy };
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
+ llvm::Value *Min = Builder.getFalse();
+ llvm::Value *NullIsUnknown = Builder.getFalse();
+ llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy);
+ llvm::Value *LargeEnough = Builder.CreateICmpUGE(
+ Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown}), Size);
+ Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
+ }
}
uint64_t AlignVal = 0;
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 76cb94618d6..d2a7f119827 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1714,10 +1714,16 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
result.getAlignment());
// Emit sanitizer checks for pointer value now, so that in the case of an
- // array it was checked only once and not at each constructor call.
+ // array it was checked only once and not at each constructor call. We may
+ // have already checked that the pointer is non-null.
+ // FIXME: If we have an array cookie and a potentially-throwing allocator,
+ // we'll null check the wrong pointer here.
+ SanitizerSet SkippedChecks;
+ SkippedChecks.set(SanitizerKind::Null, nullCheck);
EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall,
- E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),
- result.getPointer(), allocType);
+ E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ result.getPointer(), allocType, result.getAlignment(),
+ SkippedChecks, numElements);
EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
allocSizeWithoutCookie);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 792caa9c089..90c99e09fc1 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2620,10 +2620,12 @@ public:
bool sanitizePerformTypeCheck() const;
/// Emit a check that \p V is the address of storage of the
- /// appropriate size and alignment for an object of type \p Type.
+ /// appropriate size and alignment for an object of type \p Type
+ /// (or if ArraySize is provided, for an array of that bound).
void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *V,
QualType Type, CharUnits Alignment = CharUnits::Zero(),
- SanitizerSet SkippedChecks = SanitizerSet());
+ SanitizerSet SkippedChecks = SanitizerSet(),
+ llvm::Value *ArraySize = nullptr);
/// 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
OpenPOWER on IntegriCloud