diff options
author | Chris Lattner <sabre@nondot.org> | 2010-07-20 20:19:24 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-07-20 20:19:24 +0000 |
commit | 6c552c1d5f47fbba00e6268d96a26ad026f2da2a (patch) | |
tree | 0db7f53769c0611ae1901d17e402351a18eef312 /lib/CodeGen/CGExprCXX.cpp | |
parent | f033f1da4a34f8df6e95e9929dc04ff54bb8fb01 (diff) |
implement rdar://5739832 - operator new should check for overflow in multiply,
causing clang to compile this code into something that correctly throws a
length error, fixing a potential integer overflow security attack:
void *test(long N) {
return new int[N];
}
int main() {
test(1L << 62);
}
We do this even when exceptions are disabled, because it is better for the
code to abort than for the attack to succeed.
This is heavily based on a patch that Fariborz wrote.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108915 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index f9c4b30d0b..cc34b3d75c 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -13,6 +13,7 @@ #include "CodeGenFunction.h" #include "CGObjCRuntime.h" +#include "llvm/Intrinsics.h" using namespace clang; using namespace CodeGen; @@ -435,11 +436,26 @@ static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context, // Emit the array size expression. NumElements = CGF.EmitScalarExpr(E->getArraySize()); - // Multiply with the type size. - llvm::Value *V = - CGF.Builder.CreateMul(NumElements, - llvm::ConstantInt::get(SizeTy, - TypeSize.getQuantity())); + // Multiply with the type size. This multiply can overflow, e.g. in: + // new double[n] + // where n is 2^30 on a 32-bit machine or 2^62 on a 64-bit machine. Because + // of this, we need to detect the overflow and ensure that an exception is + // called by invoking std::__throw_length_error. + llvm::Value *UMulF = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, + &SizeTy, 1); + llvm::Value *MulRes = CGF.Builder.CreateCall2(UMulF, NumElements, + llvm::ConstantInt::get(SizeTy, + TypeSize.getQuantity())); + // Branch on the overflow bit to the overflow block, which is lazily created. + llvm::Value *DidOverflow = CGF.Builder.CreateExtractValue(MulRes, 1); + + llvm::BasicBlock *NormalBB = CGF.createBasicBlock("no_overflow"); + + CGF.Builder.CreateCondBr(DidOverflow, CGF.getThrowLengthErrorBB(), NormalBB); + CGF.EmitBlock(NormalBB); + + // Get the normal result of the multiplication. + llvm::Value *V = CGF.Builder.CreateExtractValue(MulRes, 0); // And add the cookie padding if necessary. if (!CookiePadding.isZero()) |