ASDenysPetrov created this revision.
ASDenysPetrov added reviewers: NoQ, martong.
Herald added subscribers: steakhal, manas, dkrupp, donat.nagy, Szelethus,
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
ASDenysPetrov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Fix a case when the extent can not be retrieved correctly from VLA declaration.
Use redeclaration to get the array extent.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D111542
Files:
clang/lib/StaticAnalyzer/Core/RegionStore.cpp
clang/test/Analysis/initialization.c
Index: clang/test/Analysis/initialization.c
===================================================================
--- clang/test/Analysis/initialization.c
+++ clang/test/Analysis/initialization.c
@@ -97,3 +97,22 @@
// FIXME: Should warn {{garbage or undefined}}.
int res = glob_arr2[x][y]; // no-warning
}
+
+const int glob_arr3[]; // VLA
+const int glob_arr3[4] = {1, 2, 3};
+void foo() {
+ clang_analyzer_eval(glob_arr3[0] == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(glob_arr3[1] == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(glob_arr3[2] == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(glob_arr3[3] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_invalid_index5() {
+ int x = 42;
+ int res = glob_arr3[x]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index6() {
+ int x = -42;
+ int res = glob_arr3[x]; // expected-warning{{garbage or undefined}}
+}
Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1660,7 +1660,7 @@
} else if (const VarRegion *VR = dyn_cast<VarRegion>(superR)) {
// Check if the containing array has an initialized value that we can trust.
// We can trust a const value or a value of a global initializer in main().
- const VarDecl *VD = VR->getDecl();
+ const VarDecl *VD = VR->getDecl()->getMostRecentDecl();
if (VD->getType().isConstQualified() ||
R->getElementType().isConstQualified() ||
(B.isMainAnalysis() && VD->hasGlobalStorage())) {
@@ -1669,48 +1669,47 @@
// The array index has to be known.
if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
// If it is not an array, return Undef.
- QualType T = VD->getType();
- const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(T);
- if (!CAT)
- return UndefinedVal();
-
- // Support one-dimensional array.
- // C++20 [expr.add] 7.6.6.4 (excerpt):
- // If P points to an array element i of an array object x with n
- // elements, where i < 0 or i > n, the behavior is undefined.
- // Dereferencing is not allowed on the "one past the last
- // element", when i == n.
- // Example:
- // const int arr[4] = {1, 2};
- // const int *ptr = arr;
- // int x0 = ptr[0]; // 1
- // int x1 = ptr[1]; // 2
- // int x2 = ptr[2]; // 0
- // int x3 = ptr[3]; // 0
- // int x4 = ptr[4]; // UB
- // TODO: Support multidimensional array.
- if (!isa<ConstantArrayType>(CAT->getElementType())) {
- // One-dimensional array.
- const llvm::APSInt &Idx = CI->getValue();
- const auto I = static_cast<uint64_t>(Idx.getExtValue());
- // Use `getZExtValue` because array extent can not be negative.
- const uint64_t Extent = CAT->getSize().getZExtValue();
- // Check for `Idx < 0`, NOT for `I < 0`, because `Idx` CAN be
- // negative, but `I` can NOT.
- if (Idx < 0 || I >= Extent)
- return UndefinedVal();
-
- // C++20 [expr.add] 9.4.17.5 (excerpt):
- // i-th array element is value-initialized for each k < i ⤠n,
- // where k is an expression-list size and n is an array extent.
- if (I >= InitList->getNumInits())
- return svalBuilder.makeZeroVal(R->getElementType());
-
- // Return a constant value, if it is presented.
- // FIXME: Support other SVals.
- const Expr *E = InitList->getInit(I);
- if (Optional<SVal> V = svalBuilder.getConstantVal(E))
- return *V;
+ const QualType T = VD->getType();
+ if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(T)) {
+ // Support one-dimensional array.
+ // C++20 [expr.add] 7.6.6.4 (excerpt):
+ // If P points to an array element i of an array object x with n
+ // elements, where i < 0 or i > n, the behavior is undefined.
+ // Dereferencing is not allowed on the "one past the last
+ // element", when i == n.
+ // Example:
+ // const int arr[4] = {1, 2};
+ // const int *ptr = arr;
+ // int x0 = ptr[0]; // 1
+ // int x1 = ptr[1]; // 2
+ // int x2 = ptr[2]; // 0
+ // int x3 = ptr[3]; // 0
+ // int x4 = ptr[4]; // UB
+ // TODO: Support multidimensional array.
+ if (!isa<ConstantArrayType>(CAT->getElementType())) {
+ // One-dimensional array.
+ const llvm::APSInt &Idx = CI->getValue();
+ const auto I = static_cast<uint64_t>(Idx.getExtValue());
+ // Use `getZExtValue` because array extent can not be negative.
+ const uint64_t Extent = CAT->getSize().getZExtValue();
+ // Check for `Idx < 0`, NOT for `I < 0`, because `Idx` CAN be
+ // negative, but `I` can NOT.
+ if (Idx < 0 || I >= Extent)
+ return UndefinedVal();
+
+ // C++20 [expr.add] 9.4.17.5 (excerpt):
+ // i-th array element is value-initialized for each k < i ⤠n,
+ // where k is an expression-list size and n is an array
+ // extent.
+ if (I >= InitList->getNumInits())
+ return svalBuilder.makeZeroVal(R->getElementType());
+
+ // Return a constant value, if it is presented.
+ // FIXME: Support other SVals.
+ const Expr *E = InitList->getInit(I);
+ if (Optional<SVal> V = svalBuilder.getConstantVal(E))
+ return *V;
+ }
}
}
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits