Skip to content

Commit 0137aa8

Browse files
author
Rafael Stahl
committedMay 29, 2018
[analyzer] const init: handle non-explicit cases more accurately
Summary: If the access is out of bounds, return UndefinedVal. If it is missing an explicit init, return the implicit zero value it must have. Reviewers: NoQ, xazax.hun, george.karpenkov Reviewed By: NoQ Subscribers: szepet, rnkovacs, a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D46823 llvm-svn: 333417
1 parent 48bf43d commit 0137aa8

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed
 

‎clang/lib/StaticAnalyzer/Core/RegionStore.cpp

+18-5
Original file line numberDiff line numberDiff line change
@@ -1638,9 +1638,18 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
16381638
// The array index has to be known.
16391639
if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
16401640
int64_t i = CI->getValue().getSExtValue();
1641-
// Return unknown value if index is out of bounds.
1642-
if (i < 0 || i >= InitList->getNumInits())
1643-
return UnknownVal();
1641+
// If it is known that the index is out of bounds, we can return
1642+
// an undefined value.
1643+
if (i < 0)
1644+
return UndefinedVal();
1645+
1646+
if (auto CAT = Ctx.getAsConstantArrayType(VD->getType()))
1647+
if (CAT->getSize().sle(i))
1648+
return UndefinedVal();
1649+
1650+
// If there is a list, but no init, it must be zero.
1651+
if (i >= InitList->getNumInits())
1652+
return svalBuilder.makeZeroVal(R->getElementType());
16441653

16451654
if (const Expr *ElemInit = InitList->getInit(i))
16461655
if (Optional<SVal> V = svalBuilder.getConstantVal(ElemInit))
@@ -1715,11 +1724,15 @@ SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
17151724
// Either the record variable or the field has to be const qualified.
17161725
if (RecordVarTy.isConstQualified() || Ty.isConstQualified())
17171726
if (const Expr *Init = VD->getInit())
1718-
if (const auto *InitList = dyn_cast<InitListExpr>(Init))
1719-
if (Index < InitList->getNumInits())
1727+
if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
1728+
if (Index < InitList->getNumInits()) {
17201729
if (const Expr *FieldInit = InitList->getInit(Index))
17211730
if (Optional<SVal> V = svalBuilder.getConstantVal(FieldInit))
17221731
return *V;
1732+
} else {
1733+
return svalBuilder.makeZeroVal(Ty);
1734+
}
1735+
}
17231736
}
17241737

17251738
return getBindingForFieldOrElementCommon(B, R, Ty);

‎clang/test/Analysis/initialization.c

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
1-
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
2-
// expected-no-diagnostics
1+
// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
2+
3+
void clang_analyzer_eval(int);
34

45
void initbug() {
56
const union { float a; } u = {};
67
(void)u.a; // no-crash
78
}
9+
10+
int const parr[2] = {1};
11+
void constarr() {
12+
int i = 2;
13+
clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}}
14+
i = 1;
15+
clang_analyzer_eval(parr[i] == 0); // expected-warning{{TRUE}}
16+
i = -1;
17+
clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}}
18+
}
19+
20+
struct SM {
21+
int a;
22+
int b;
23+
};
24+
const struct SM sm = {.a = 1};
25+
void multinit() {
26+
clang_analyzer_eval(sm.a == 1); // expected-warning{{TRUE}}
27+
clang_analyzer_eval(sm.b == 0); // expected-warning{{TRUE}}
28+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
2+
3+
void clang_analyzer_eval(int);
4+
5+
struct S {
6+
int a = 3;
7+
};
8+
S const sarr[2] = {};
9+
void definit() {
10+
int i = 1;
11+
// FIXME: Should recognize that it is 3.
12+
clang_analyzer_eval(sarr[i].a); // expected-warning{{UNKNOWN}}
13+
}
14+
15+
int const arr[2][2] = {};
16+
void arr2init() {
17+
int i = 1;
18+
// FIXME: Should recognize that it is 0.
19+
clang_analyzer_eval(arr[i][0]); // expected-warning{{UNKNOWN}}
20+
}

0 commit comments

Comments
 (0)
Please sign in to comment.