Author: dergachev Date: Wed Jan 17 14:58:35 2018 New Revision: 322780 URL: http://llvm.org/viewvc/llvm-project?rev=322780&view=rev Log: [analyzer] operator new: Fix memory space for the returned region.
Make sure that with c++-allocator-inlining=true we have the return value of conservatively evaluated operator new() in the correct memory space (heap). This is a regression/omission that worked well in c++-allocator-inlining=false. Heap regions are superior to regular symbolic regions because they have stricter aliasing constraints: heap regions do not alias each other or global variables. Differential Revision: https://reviews.llvm.org/D41266 rdar://problem/12180598 Added: cfe/trunk/test/Analysis/new-ctor-null.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp cfe/trunk/test/Analysis/NewDelete-checker-test.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=322780&r1=322779&r2=322780&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Jan 17 14:58:35 2018 @@ -479,8 +479,10 @@ void ExprEngine::VisitCXXNewAllocatorCal ExplodedNodeSet DstPostCall; StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx); - for (auto I : DstPreCall) + for (auto I : DstPreCall) { + // FIXME: Provide evalCall for checkers? defaultEvalCall(CallBldr, I, *Call); + } // If the call is inlined, DstPostCall will be empty and we bail out now. // Store return value of operator new() for future use, until the actual @@ -507,7 +509,6 @@ void ExprEngine::VisitCXXNewAllocatorCal *Call, *this); } - void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { // FIXME: Much of this should eventually migrate to CXXAllocatorCall. @@ -520,18 +521,8 @@ void ExprEngine::VisitCXXNewExpr(const C SVal symVal = UnknownVal(); FunctionDecl *FD = CNE->getOperatorNew(); - bool IsStandardGlobalOpNewFunction = false; - if (FD && !isa<CXXMethodDecl>(FD) && !FD->isVariadic()) { - if (FD->getNumParams() == 2) { - QualType T = FD->getParamDecl(1)->getType(); - if (const IdentifierInfo *II = T.getBaseTypeIdentifier()) - // NoThrow placement new behaves as a standard new. - IsStandardGlobalOpNewFunction = II->getName().equals("nothrow_t"); - } - else - // Placement forms are considered non-standard. - IsStandardGlobalOpNewFunction = (FD->getNumParams() == 1); - } + bool IsStandardGlobalOpNewFunction = + FD->isReplaceableGlobalAllocationFunction(); ProgramStateRef State = Pred->getState(); @@ -587,9 +578,8 @@ void ExprEngine::VisitCXXNewExpr(const C if (CNE->isArray()) { // FIXME: allocating an array requires simulating the constructors. // For now, just return a symbolicated region. - if (!AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) { - const SubRegion *NewReg = - symVal.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>(); + if (const SubRegion *NewReg = + dyn_cast_or_null<SubRegion>(symVal.getAsRegion())) { QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); const ElementRegion *EleReg = getStoreManager().GetElementZeroRegion(NewReg, ObjTy); Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=322780&r1=322779&r2=322780&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Wed Jan 17 14:58:35 2018 @@ -573,7 +573,19 @@ ProgramStateRef ExprEngine::bindReturnVa QualType ResultTy = Call.getResultType(); SValBuilder &SVB = getSValBuilder(); unsigned Count = currBldrCtx->blockCount(); - SVal R = SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count); + + // See if we need to conjure a heap pointer instead of + // a regular unknown pointer. + bool IsHeapPointer = false; + if (const auto *CNE = dyn_cast<CXXNewExpr>(E)) + if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) { + // FIXME: Delegate this to evalCall in MallocChecker? + IsHeapPointer = true; + } + + SVal R = IsHeapPointer + ? SVB.getConjuredHeapSymbolVal(E, LCtx, Count) + : SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count); return State->BindExpr(E, LCtx, R); } Modified: cfe/trunk/test/Analysis/NewDelete-checker-test.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=322780&r1=322779&r2=322780&view=diff ============================================================================== --- cfe/trunk/test/Analysis/NewDelete-checker-test.cpp (original) +++ cfe/trunk/test/Analysis/NewDelete-checker-test.cpp Wed Jan 17 14:58:35 2018 @@ -1,5 +1,7 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s #include "Inputs/system-header-simulator-cxx.h" typedef __typeof__(sizeof(int)) size_t; Added: cfe/trunk/test/Analysis/new-ctor-null.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/new-ctor-null.cpp?rev=322780&view=auto ============================================================================== --- cfe/trunk/test/Analysis/new-ctor-null.cpp (added) +++ cfe/trunk/test/Analysis/new-ctor-null.cpp Wed Jan 17 14:58:35 2018 @@ -0,0 +1,23 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify %s + +void clang_analyzer_eval(bool); + +typedef __typeof__(sizeof(int)) size_t; + +void *operator new(size_t size) throw() { + return nullptr; +} +void *operator new[](size_t size) throw() { + return nullptr; +} + +struct S { + int x; + S() : x(1) {} + ~S() {} +}; + +void testArrays() { + S *s = new S[10]; // no-crash + s[0].x = 2; // expected-warning{{Dereference of null pointer}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits