From 26008e07dea3ca4e4ee1f7634923059ea7f17f7a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 20 Jul 2010 20:19:24 +0000 Subject: 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. llvm-svn: 108915 --- clang/lib/CodeGen/CGExprCXX.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'clang/lib/CodeGen/CGExprCXX.cpp') diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index f9c4b30d0ba..cc34b3d75c6 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/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()) -- cgit v1.2.3