Charusso updated this revision to Diff 227534.
Charusso marked 6 inline comments as done.
Charusso added a comment.
- Fix.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D69726/new/
https://reviews.llvm.org/D69726
Files:
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSizeInfo.h
clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
clang/lib/StaticAnalyzer/Core/DynamicSize.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
@@ -18,6 +17,8 @@
#include "clang/Analysis/ConstructionContext.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -653,16 +654,21 @@
// 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;
+ const auto *CNE = dyn_cast<CXXNewExpr>(E);
+ if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+ // FIXME: Delegate this to evalCall in MallocChecker?
+ DefinedOrUnknownSVal Size = UnknownVal();
+ const Expr *SizeExpr = nullptr;
+
+ if ((SizeExpr = CNE->getArraySize().getValueOr(nullptr))) {
+ Size = State->getSVal(SizeExpr, LCtx).castAs<DefinedOrUnknownSVal>();
}
- R = IsHeapPointer ? svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count)
- : svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy,
- Count);
+ R = svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count);
+ State = setDynamicSize(State, R.getAsRegion(), Size, SizeExpr);
+ } else {
+ R = svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+ }
}
return State->BindExpr(E, LCtx, R);
}
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -10,15 +10,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/Analysis/ConstructionContext.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Analysis/ConstructionContext.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
using namespace ento;
@@ -761,11 +762,20 @@
// heap. We realize this is an approximation that might not correctly model
// a custom global allocator.
if (symVal.isUnknown()) {
- if (IsStandardGlobalOpNewFunction)
+ if (IsStandardGlobalOpNewFunction) {
+ DefinedOrUnknownSVal Size = UnknownVal();
+ const Expr *SizeExpr = nullptr;
+
+ if ((SizeExpr = CNE->getArraySize().getValueOr(nullptr))) {
+ Size = State->getSVal(SizeExpr, LCtx).castAs<DefinedOrUnknownSVal>();
+ }
+
symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
- else
+ State = setDynamicSize(State, symVal.getAsRegion(), Size, SizeExpr);
+ } else {
symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
blockCount);
+ }
}
CallEventManager &CEMgr = getStateManager().getCallEventManager();
Index: clang/lib/StaticAnalyzer/Core/DynamicSize.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/DynamicSize.cpp
+++ clang/lib/StaticAnalyzer/Core/DynamicSize.cpp
@@ -13,20 +13,40 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSizeInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+REGISTER_MAP_WITH_PROGRAMSTATE(DynamicSizeMap, const clang::ento::MemRegion *,
+ clang::ento::DynamicSizeInfo)
+
namespace clang {
namespace ento {
+ProgramStateRef setDynamicSize(ProgramStateRef State, const MemRegion *MR,
+ DefinedOrUnknownSVal Size,
+ const Expr *SizeExpr) {
+ return State->set<DynamicSizeMap>(MR, {Size, SizeExpr});
+}
+
DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
SValBuilder &SVB) {
+ if (const DynamicSizeInfo *SizeInfo = State->get<DynamicSizeMap>(MR))
+ return SizeInfo->getSize();
+
return MR->getMemRegionManager().getStaticSize(MR, SVB);
}
+const Expr *getDynamicSizeExpr(ProgramStateRef State, const MemRegion *MR) {
+ if (const DynamicSizeInfo *SizeInfo = State->get<DynamicSizeMap>(MR))
+ return SizeInfo->getSizeExpr();
+
+ return nullptr;
+}
+
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
const MemRegion *MR,
SValBuilder &SVB,
Index: clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -166,18 +166,9 @@
SVal ArraySizeVal = svalBuilder.evalBinOpNN(
state, BO_Mul, ArrayLength, EleSizeVal.castAs<NonLoc>(), SizeTy);
- // Finally, assume that the array's size matches the given size.
- const LocationContext *LC = C.getLocationContext();
- DefinedOrUnknownSVal DynSize =
- getDynamicSize(state, state->getRegion(VD, LC), svalBuilder);
-
- DefinedOrUnknownSVal ArraySize = ArraySizeVal.castAs<DefinedOrUnknownSVal>();
- DefinedOrUnknownSVal sizeIsKnown =
- svalBuilder.evalEQ(state, DynSize, ArraySize);
- state = state->assume(sizeIsKnown, true);
-
- // Assume should not fail at this point.
- assert(state);
+ // Finally, set the size.
+ state = setDynamicSize(state, state->getRegion(VD, C.getLocationContext()),
+ ArraySizeVal.castAs<DefinedOrUnknownSVal>(), SE);
// Remember our assumptions!
C.addTransition(state);
Index: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -441,29 +441,30 @@
/// Models memory allocation.
///
/// \param [in] CE The expression that allocates memory.
- /// \param [in] SizeEx Size of the memory that needs to be allocated.
+ /// \param [in] SizeExpr Size of the memory that needs to be allocated.
/// \param [in] Init The value the allocated memory needs to be initialized.
/// with. For example, \c calloc initializes the allocated memory to 0,
/// malloc leaves it undefined.
/// \param [in] State The \c ProgramState right before allocation.
/// \returns The ProgramState right after allocation.
static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
- const Expr *SizeEx, SVal Init,
+ const Expr *SizeExpr, SVal Init,
ProgramStateRef State,
AllocationFamily Family = AF_Malloc);
/// Models memory allocation.
///
/// \param [in] CE The expression that allocates memory.
- /// \param [in] Size Size of the memory that needs to be allocated.
+ /// \param [in] Size Symbolic size of the memory that needs to be allocated.
+ /// \param [in] SizeExpr Size expression of the memory allocation.
/// \param [in] Init The value the allocated memory needs to be initialized.
/// with. For example, \c calloc initializes the allocated memory to 0,
/// malloc leaves it undefined.
/// \param [in] State The \c ProgramState right before allocation.
/// \returns The ProgramState right after allocation.
static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
- SVal Size, SVal Init,
- ProgramStateRef State,
+ const Expr *SizeExpr, SVal Size,
+ SVal Init, ProgramStateRef State,
AllocationFamily Family = AF_Malloc);
static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE,
@@ -1163,8 +1164,8 @@
} else if (FunI == MemFunctionInfo.II_if_nameindex) {
// Should we model this differently? We can allocate a fixed number of
// elements with zeros in the last one.
- State = MallocMemAux(C, CE, UnknownVal(), UnknownVal(), State,
- AF_IfNameIndex);
+ State = MallocMemAux(C, CE, /*SizeExpr=*/nullptr, UnknownVal(),
+ UnknownVal(), State, AF_IfNameIndex);
} else if (FunI == MemFunctionInfo.II_if_freenameindex) {
State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory);
} else if (FunI == MemFunctionInfo.II_g_malloc0 ||
@@ -1193,7 +1194,8 @@
Init = SB.makeZeroVal(SB.getContext().CharTy);
}
SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));
- State = MallocMemAux(C, CE, TotalSize, Init, State);
+ State = MallocMemAux(C, CE, /*SizeExpr=*/CE->getArg(0), TotalSize, Init,
+ State);
State = ProcessZeroAllocCheck(C, CE, 0, State);
State = ProcessZeroAllocCheck(C, CE, 1, State);
} else if (FunI == MemFunctionInfo.II_g_realloc_n ||
@@ -1403,16 +1405,15 @@
CharUnits TypeSize = AstContext.getTypeSizeInChars(ElementType);
if (ElementCount.getAs<NonLoc>()) {
- DefinedOrUnknownSVal DynSize = getDynamicSize(State, Region, svalBuilder);
-
// size in Bytes = ElementCount*TypeSize
SVal SizeInBytes = svalBuilder.evalBinOpNN(
State, BO_Mul, ElementCount.castAs<NonLoc>(),
svalBuilder.makeArrayIndex(TypeSize.getQuantity()),
svalBuilder.getArrayIndexType());
- DefinedOrUnknownSVal DynSizeMatchesSize = svalBuilder.evalEQ(
- State, DynSize, SizeInBytes.castAs<DefinedOrUnknownSVal>());
- State = State->assume(DynSizeMatchesSize, true);
+
+ State = setDynamicSize(State, Region,
+ SizeInBytes.castAs<DefinedOrUnknownSVal>(),
+ NE->getArraySize().getValueOr(nullptr));
}
return State;
}
@@ -1495,25 +1496,27 @@
return MallocMemAux(C, CE, CE->getArg(I->getASTIndex()), UndefinedVal(),
State);
}
- return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
+ return MallocMemAux(C, CE, /*SizeExpr=*/nullptr, UnknownVal(), UndefinedVal(),
+ State);
}
ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
const CallExpr *CE,
- const Expr *SizeEx, SVal Init,
+ const Expr *SizeExpr, SVal Init,
ProgramStateRef State,
AllocationFamily Family) {
if (!State)
return nullptr;
- return MallocMemAux(C, CE, C.getSVal(SizeEx), Init, State, Family);
+ return MallocMemAux(C, CE, SizeExpr, C.getSVal(SizeExpr), Init, State,
+ Family);
}
ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
- const CallExpr *CE,
- SVal Size, SVal Init,
- ProgramStateRef State,
- AllocationFamily Family) {
+ const CallExpr *CE,
+ const Expr *SizeExpr, SVal Size,
+ SVal Init, ProgramStateRef State,
+ AllocationFamily Family) {
if (!State)
return nullptr;
@@ -1534,21 +1537,9 @@
// Fill the region with the initialization value.
State = State->bindDefaultInitial(RetVal, Init, LCtx);
- // Set the region's extent equal to the Size parameter.
- const SymbolicRegion *R =
- dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
- if (!R)
- return nullptr;
- if (Optional<DefinedOrUnknownSVal> DefinedSize =
- Size.getAs<DefinedOrUnknownSVal>()) {
- DefinedOrUnknownSVal DynSize = getDynamicSize(State, R, svalBuilder);
-
- DefinedOrUnknownSVal DynSizeMatchesSize =
- svalBuilder.evalEQ(State, DynSize, *DefinedSize);
-
- State = State->assume(DynSizeMatchesSize, true);
- assert(State);
- }
+ // Set the region's size.
+ State = setDynamicSize(State, RetVal.getAsRegion(),
+ Size.castAs<DefinedOrUnknownSVal>(), SizeExpr);
return MallocUpdateRefState(C, CE, State, Family);
}
@@ -2442,8 +2433,8 @@
// If the ptr is NULL and the size is not 0, the call is equivalent to
// malloc(size).
if (PrtIsNull && !SizeIsZero) {
- ProgramStateRef stateMalloc = MallocMemAux(C, CE, TotalSize,
- UndefinedVal(), StatePtrIsNull);
+ ProgramStateRef stateMalloc =
+ MallocMemAux(C, CE, Arg1, TotalSize, UndefinedVal(), StatePtrIsNull);
return stateMalloc;
}
@@ -2474,8 +2465,8 @@
if (ProgramStateRef stateFree =
FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocated)) {
- ProgramStateRef stateRealloc = MallocMemAux(C, CE, TotalSize,
- UnknownVal(), stateFree);
+ ProgramStateRef stateRealloc =
+ MallocMemAux(C, CE, Arg1, TotalSize, UnknownVal(), stateFree);
if (!stateRealloc)
return nullptr;
@@ -2508,7 +2499,7 @@
SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));
- return MallocMemAux(C, CE, TotalSize, zeroVal, State);
+ return MallocMemAux(C, CE, CE->getArg(0), TotalSize, zeroVal, State);
}
MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
Index: clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -90,12 +90,8 @@
if (Size.isUndef())
return true; // Return true to model purity.
- SValBuilder& svalBuilder = C.getSValBuilder();
- DefinedOrUnknownSVal DynSize = getDynamicSize(state, R, svalBuilder);
- DefinedOrUnknownSVal DynSizeMatchesSizeArg =
- svalBuilder.evalEQ(state, DynSize, Size.castAs<DefinedOrUnknownSVal>());
- state = state->assume(DynSizeMatchesSizeArg, true);
- assert(state && "The region should not have any previous constraints");
+ state = setDynamicSize(state, R, Size.castAs<DefinedOrUnknownSVal>(),
+ Call.getArgExpr(0));
C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
return true;
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSizeInfo.h
===================================================================
--- /dev/null
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSizeInfo.h
@@ -0,0 +1,45 @@
+//===- DynamicSizeInfo.h - Runtime size information -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICSIZEINFO_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICSIZEINFO_H
+
+namespace clang {
+namespace ento {
+
+#include "clang/AST/Expr.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+
+/// Helper class to store information about the dynamic size.
+class DynamicSizeInfo {
+public:
+ DynamicSizeInfo(DefinedOrUnknownSVal Size, const Expr *SizeExpr = nullptr)
+ : Size(Size), SizeExpr(SizeExpr) {}
+
+ DefinedOrUnknownSVal getSize() const { return Size; }
+ const Expr *getSizeExpr() const { return SizeExpr; }
+
+ bool operator==(const DynamicSizeInfo &RHS) const {
+ return Size == RHS.Size && SizeExpr == RHS.SizeExpr;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.Add(Size);
+ ID.AddPointer(SizeExpr);
+ }
+
+private:
+ DefinedOrUnknownSVal Size;
+ const Expr *SizeExpr;
+};
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICSIZEINFO_H
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h
@@ -22,16 +22,24 @@
namespace clang {
namespace ento {
-/// Get the stored dynamic size for the region \p MR.
+/// \returns The stored dynamic size for the region \p MR.
DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
SValBuilder &SVB);
-/// Get the stored element count of the region \p MR.
+/// \returns The stored dynamic size expression for the region \p MR.
+const Expr *getDynamicSizeExpr(ProgramStateRef State, const MemRegion *MR);
+
+/// \returns The stored element count of the region \p MR.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
const MemRegion *MR,
SValBuilder &SVB,
QualType ElementTy);
+/// Set the dynamic size \p Size with its expression \p SizeExpr of the region
+/// \p MR.
+ProgramStateRef setDynamicSize(ProgramStateRef State, const MemRegion *MR,
+ DefinedOrUnknownSVal Size, const Expr *SizeExpr);
+
} // namespace ento
} // namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits