Skip to content

Commit 8015928

Browse files
committed
Merging r353943:
------------------------------------------------------------------------ r353943 | baloghadamsoftware | 2019-02-13 13:25:47 +0100 (Wed, 13 Feb 2019) | 22 lines [Analyzer] Crash fix for FindLastStoreBRVisitor FindLastStoreBRVisitor tries to find the first node in the exploded graph where the current value was assigned to a region. This node is called the "store site". It is identified by a pair of Pred and Succ nodes where Succ already has the binding for the value while Pred does not have it. However the visitor mistakenly identifies a node pair as the store site where the value is a `LazyCompoundVal` and `Pred` does not have a store yet but `Succ` has it. In this case the `LazyCompoundVal` is different in the `Pred` node because it also contains the store which is different in the two nodes. This error may lead to crashes (a declaration is cast to a parameter declaration without check) or misleading bug path notes. In this patch we fix this problem by checking for unequal `LazyCompoundVals`: if their region is equal, and their store is the same as the store of their nodes we consider them as equal when looking for the "store site". This is an approximation because we do not check for differences of the subvalues (structure members or array elements) in the stores. Differential Revision: https://reviews.llvm.org/D58067 ------------------------------------------------------------------------ llvm-svn: 354130
1 parent ff29092 commit 8015928

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,32 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
154154
return E;
155155
}
156156

157+
/// Comparing internal representations of symbolic values (via
158+
/// SVal::operator==()) is a valid way to check if the value was updated,
159+
/// unless it's a LazyCompoundVal that may have a different internal
160+
/// representation every time it is loaded from the state. In this function we
161+
/// do an approximate comparison for lazy compound values, checking that they
162+
/// are the immediate snapshots of the tracked region's bindings within the
163+
/// node's respective states but not really checking that these snapshots
164+
/// actually contain the same set of bindings.
165+
bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
166+
const ExplodedNode *RightNode, SVal RightVal) {
167+
if (LeftVal == RightVal)
168+
return true;
169+
170+
const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
171+
if (!LLCV)
172+
return false;
173+
174+
const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
175+
if (!RLCV)
176+
return false;
177+
178+
return LLCV->getRegion() == RLCV->getRegion() &&
179+
LLCV->getStore() == LeftNode->getState()->getStore() &&
180+
RLCV->getStore() == RightNode->getState()->getStore();
181+
}
182+
157183
//===----------------------------------------------------------------------===//
158184
// Definitions for bug reporter visitors.
159185
//===----------------------------------------------------------------------===//
@@ -1188,7 +1214,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
11881214
if (Succ->getState()->getSVal(R) != V)
11891215
return nullptr;
11901216

1191-
if (Pred->getState()->getSVal(R) == V) {
1217+
if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) {
11921218
Optional<PostStore> PS = Succ->getLocationAs<PostStore>();
11931219
if (!PS || PS->getLocationValue() != R)
11941220
return nullptr;
@@ -1209,6 +1235,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
12091235
// UndefinedVal.)
12101236
if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
12111237
if (const auto *VR = dyn_cast<VarRegion>(R)) {
1238+
12121239
const auto *Param = cast<ParmVarDecl>(VR->getDecl());
12131240

12141241
ProgramStateManager &StateMgr = BRC.getStateManager();

clang/test/Analysis/PR40625.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core.CallAndMessageUnInitRefArg %s -verify
2+
3+
void f(const int *end);
4+
5+
void g(const int (&arrr)[10]) {
6+
f(arrr+sizeof(arrr)); // expected-warning{{1st function call argument is a pointer to uninitialized value}}
7+
// FIXME: This is a false positive that should be fixed. Until then this
8+
// tests the crash fix in FindLastStoreBRVisitor (beside
9+
// uninit-vals.m).
10+
}
11+
12+
void h() {
13+
int arr[10];
14+
15+
g(arr);
16+
}

clang/test/Analysis/uninit-vals.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,11 +394,11 @@ void testSmallStructBitfieldsFirstUnnamed() {
394394
struct {
395395
int : 4;
396396
int y : 4;
397-
} a, b, c;
397+
} a, b, c; // expected-note{{'c' initialized here}}
398398

399399
a.y = 2;
400400

401-
b = a; // expected-note{{Value assigned to 'c'}}
401+
b = a;
402402
clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
403403
// expected-note@-1{{TRUE}}
404404

@@ -411,11 +411,11 @@ void testSmallStructBitfieldsSecondUnnamed() {
411411
struct {
412412
int x : 4;
413413
int : 4;
414-
} a, b, c;
414+
} a, b, c; // expected-note{{'c' initialized here}}
415415

416416
a.x = 1;
417417

418-
b = a; // expected-note{{Value assigned to 'c'}}
418+
b = a;
419419
clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
420420
// expected-note@-1{{TRUE}}
421421

0 commit comments

Comments
 (0)