aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorTomasz Kamiński <tomasz.kamiński@sonarsource.com>2022-11-09 14:31:49 +0100
committerTomasz Kamiński <tomasz.kamiński@sonarsource.com>2022-11-09 15:06:46 +0100
commit2fb3bec932ede7704724abb71e8270e0b4c201f6 (patch)
treedb442e79e6132447aee50e6a4fe045751b60afe7 /clang
parent3dbda5ff88518912bbb72f03d95805634507ac17 (diff)
downloadllvm-2fb3bec932ede7704724abb71e8270e0b4c201f6.zip
llvm-2fb3bec932ede7704724abb71e8270e0b4c201f6.tar.gz
llvm-2fb3bec932ede7704724abb71e8270e0b4c201f6.tar.bz2
[analyzer] Fix crash for array-delete of UnknownVal values.
We now skip the destruction of array elements for `delete[] p`, if the value of `p` is UnknownVal and does not have corresponding region. This eliminate the crash in `getDynamicElementCount` on that region and matches the behavior for deleting the array of non-constant range. Reviewed By: isuckatcs Differential Revision: https://reviews.llvm.org/D136671
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp1
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp34
-rw-r--r--clang/test/Analysis/dtor-array.cpp33
3 files changed, 52 insertions, 16 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
index db9698b..6a86536 100644
--- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -44,6 +44,7 @@ DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
const MemRegion *MR,
SValBuilder &SVB,
QualType ElementTy) {
+ assert(MR != nullptr && "Not-null region expected");
MR = MR->StripCasts();
DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index a90e17f..4528dbc 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1241,6 +1241,7 @@ ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
const QualType &ElementTy,
const LocationContext *LCtx,
SVal *ElementCountVal) {
+ assert(Region != nullptr && "Not-null region expected");
QualType Ty = ElementTy.getDesugaredType(getContext());
while (const auto *NTy = dyn_cast<ArrayType>(Ty))
@@ -1420,31 +1421,32 @@ void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
const MemRegion *ArgR = ArgVal.getAsRegion();
if (DE->isArrayForm()) {
- SVal ElementCount;
- std::tie(State, Idx) =
- prepareStateForArrayDestruction(State, ArgR, DTy, LCtx, &ElementCount);
-
CallOpts.IsArrayCtorOrDtor = true;
// Yes, it may even be a multi-dimensional array.
while (const auto *AT = getContext().getAsArrayType(DTy))
DTy = AT->getElementType();
- // If we're about to destruct a 0 length array, don't run any of the
- // destructors.
- if (ElementCount.isConstant() &&
- ElementCount.getAsInteger()->getLimitedValue() == 0) {
+ if (ArgR) {
+ SVal ElementCount;
+ std::tie(State, Idx) = prepareStateForArrayDestruction(
+ State, ArgR, DTy, LCtx, &ElementCount);
- static SimpleProgramPointTag PT(
- "ExprEngine", "Skipping 0 length array delete destruction");
- PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT);
- NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
- Bldr.generateNode(PP, Pred->getState(), Pred);
- return;
- }
+ // If we're about to destruct a 0 length array, don't run any of the
+ // destructors.
+ if (ElementCount.isConstant() &&
+ ElementCount.getAsInteger()->getLimitedValue() == 0) {
+
+ static SimpleProgramPointTag PT(
+ "ExprEngine", "Skipping 0 length array delete destruction");
+ PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx, &PT);
+ NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ Bldr.generateNode(PP, Pred->getState(), Pred);
+ return;
+ }
- if (ArgR)
ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
.getAsRegion();
+ }
}
NodeBuilder Bldr(Pred, Dst, getBuilderContext());
diff --git a/clang/test/Analysis/dtor-array.cpp b/clang/test/Analysis/dtor-array.cpp
index ab0a939..84a34af 100644
--- a/clang/test/Analysis/dtor-array.cpp
+++ b/clang/test/Analysis/dtor-array.cpp
@@ -344,3 +344,36 @@ void nonConstantRegionExtent(){
// region to a conjured symbol.
clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}} expected-warning {{FALSE}}
}
+
+namespace crash6 {
+
+struct NonTrivialItem {
+ ~NonTrivialItem();
+};
+
+struct WeirdVec {
+ void clear() {
+ delete[] data;
+ size = 0;
+ }
+ NonTrivialItem *data;
+ unsigned size;
+};
+
+void top(int j) {
+ WeirdVec *p = new WeirdVec;
+
+ p[j].size = 0;
+ delete[] p->data; // no-crash
+}
+
+template <typename T>
+T make_unknown() {
+ return reinterpret_cast<T>(static_cast<int>(0.404));
+}
+
+void directUnknownSymbol() {
+ delete[] make_unknown<NonTrivialItem*>(); // no-crash
+}
+
+}