[PATCH] D108032: [analyzer] Retrieve a character from CompoundLiteralExpr as an initializer for constant arrays.

2022-01-27 Thread Denys Petrov via Phabricator via cfe-commits
ASDenysPetrov abandoned this revision.
ASDenysPetrov added a comment.

Paused for a while.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108032/new/

https://reviews.llvm.org/D108032

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D108032: [analyzer] Retrieve a character from CompoundLiteralExpr as an initializer for constant arrays.

2021-09-21 Thread Denys Petrov via Phabricator via cfe-commits
ASDenysPetrov updated this revision to Diff 373964.
ASDenysPetrov edited the summary of this revision.
ASDenysPetrov added a comment.

Rebased.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108032/new/

https://reviews.llvm.org/D108032

Files:
  clang/lib/StaticAnalyzer/Core/RegionStore.cpp
  clang/test/Analysis/compound-literals.c

Index: clang/test/Analysis/compound-literals.c
===
--- clang/test/Analysis/compound-literals.c
+++ clang/test/Analysis/compound-literals.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple=i386-apple-darwin10 -verify %s -analyze \
-// RUN:   -analyzer-checker=debug.ExprInspection
+// RUN:   -analyzer-checker=debug.ExprInspection,core.uninitialized.Assign
 
 #define NULL 0
 void clang_analyzer_eval(int);
@@ -21,3 +21,63 @@
   clang_analyzer_eval(pointers[0] == NULL); // expected-warning{{FALSE}}
   clang_analyzer_eval(pointers[1] == NULL); // expected-warning{{TRUE}}
 }
+
+const int glob_arr1[8] = (const int[8]){[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+void glob_arr_index1() {
+  clang_analyzer_eval(glob_arr1[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr1[7] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_invalid_index1() {
+  int x = -42;
+  int res = glob_arr1[x]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index2() {
+  int x = 42;
+  int res = glob_arr1[x]; // expected-warning{{garbage or undefined}}
+}
+
+const int glob_arr2[8] = (const int[8]){1, 2, 3, 4};
+void glob_arr_index2() {
+  clang_analyzer_eval(glob_arr2[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr2[7] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_ptr_index1() {
+  int const *ptr = glob_arr2;
+  clang_analyzer_eval(ptr[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[7] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr[8] == 0); // expected-warning{{UNDEFINED}}
+  clang_analyzer_eval(ptr[9] == 0); // expected-warning{{UNDEFINED}}
+}
+
+void glob_invalid_index3() {
+  int const *ptr = glob_arr2;
+  int idx = -42;
+  int res = ptr[idx]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index4() {
+  int const *ptr = glob_arr2;
+  int idx = 42;
+  int res = ptr[idx]; // expected-warning{{garbage or undefined}}
+}
Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1680,52 +1680,63 @@
 QualType ElemT = R->getElementType();
 return getSValFromStringLiteralByIndex(SL, Idx, ElemT);
   }
-} else if (const auto *InitList = dyn_cast(Init)) {
-  // The array index has to be known.
-  if (auto CI = R->getIndex().getAs()) {
-// 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
-// 

[PATCH] D108032: [analyzer] Retrieve a character from CompoundLiteralExpr as an initializer for constant arrays.

2021-08-13 Thread Denys Petrov via Phabricator via cfe-commits
ASDenysPetrov created this revision.
ASDenysPetrov added reviewers: NoQ, vsavchenko, steakhal, martong.
ASDenysPetrov added a project: clang.
Herald added subscribers: manas, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
ASDenysPetrov requested review of this revision.
Herald added a subscriber: cfe-commits.

Add support of handling `CompoundLiteralExpr` in 
`RegionStoreManager::getConstantValFromConstArrayInitializer`. Retrieve a value 
from `CompoundLiteralExpr` which is an initializer of constant arrays in global 
and local scopes. This patch also disables direct binding a compound literal 
for constant arrays of local storage duration.

Example:

  const int arr[8] = (const int[8]){1, 2, 3, 4}; // compound literal


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D108032

Files:
  clang/lib/AST/Expr.cpp
  clang/lib/StaticAnalyzer/Core/RegionStore.cpp
  clang/test/Analysis/compound-literals.c

Index: clang/test/Analysis/compound-literals.c
===
--- clang/test/Analysis/compound-literals.c
+++ clang/test/Analysis/compound-literals.c
@@ -21,3 +21,139 @@
   clang_analyzer_eval(pointers[0] == NULL); // expected-warning{{FALSE}}
   clang_analyzer_eval(pointers[1] == NULL); // expected-warning{{TRUE}}
 }
+
+void local_arr_index2() {
+  const int local_arr[8] = (const int[8]){[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+  clang_analyzer_eval(local_arr[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[7] == 0); // expected-warning{{TRUE}}
+}
+
+void local_arr_out_of_bound_index3() {
+  const int local_arr[8] = (const int[8]){[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+  int x = -42;
+  int res = local_arr[x]; // expected-warning{{garbage or undefined}}
+}
+
+void local_arr_out_of_bound_index4() {
+  const int local_arr[8] = (const int[8]){[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+  int x = 42;
+  int res = local_arr[x]; // expected-warning{{garbage or undefined}}
+}
+
+void local_arr_index3() {
+  const int local_arr[8] = (const int[8]){1, 2, 3, 4};
+  clang_analyzer_eval(local_arr[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[7] == 0); // expected-warning{{TRUE}}
+}
+
+void local_arr_index4() {
+  int const local_arr[][2][3] = (int const[2][2][3]){{{1, 2}, {}}, {{7, 8}, {10, 11, 12}}};
+  clang_analyzer_eval(local_arr[0][0][0] == 1);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][0][1] == 2);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][0][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][0] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][1] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][0] == 7);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][1] == 8);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][0] == 10); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][1] == 11); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][2] == 12); // expected-warning{{TRUE}}
+}
+
+void local_arr_index5() {
+  int const(*ptr_arr)[2][3] = (int const[2][2][3]){{{1, 2}, {}}, {{7, 8}, {10, 11, 12}}};
+  clang_analyzer_eval(ptr_arr[0][0][0] == 1);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[0][0][1] == 2);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[0][0][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[0][1][0] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[0][1][1] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[0][1][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[1][0][0] == 7);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[1][0][1] == 8);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr_arr[1][0][2] == 0);  // expected-warning{{TRUE}}
+