Skip to content

Commit 4163136

Browse files
authored
[analyzer][Solver] Early return if sym is concrete on assuming (#115579)
This could deduce some complex syms derived from simple ones whose values could be constrainted to be concrete during execution, thus reducing some overconstrainted states. This commit also fix `unix.StdCLibraryFunctions` crash due to these overconstrainted states being added to the graph, which is marked as sink node (PosteriorlyOverconstrained). The 'assume' API is used in non-dual style so the checker should protectively test whether these newly added nodes are actually impossible. 1. The crash: https://godbolt.org/z/8KKWeKb86 2. The solver needs to solve equivalent: https://godbolt.org/z/ed8WqsbTh
1 parent a1a1a4c commit 4163136

6 files changed

+94
-5
lines changed

clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,8 @@ void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
13541354
if (BR.isInteresting(ArgSVal))
13551355
OS << Msg;
13561356
}));
1357+
if (NewNode->isSink())
1358+
break;
13571359
}
13581360
}
13591361
}

clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ ConstraintManager::assumeDualImpl(ProgramStateRef &State,
7474
// it might happen that a Checker uncoditionally uses one of them if the
7575
// other is a nullptr. This may also happen with the non-dual and
7676
// adjacent `assume(true)` and `assume(false)` calls. By implementing
77-
// assume in therms of assumeDual, we can keep our API contract there as
77+
// assume in terms of assumeDual, we can keep our API contract there as
7878
// well.
7979
return ProgramStatePair(StInfeasible, StInfeasible);
8080
}

clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ RangedConstraintManager::~RangedConstraintManager() {}
2323
ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State,
2424
SymbolRef Sym,
2525
bool Assumption) {
26-
Sym = simplify(State, Sym);
26+
SVal SimplifiedVal = simplifyToSVal(State, Sym);
27+
if (SimplifiedVal.isConstant()) {
28+
bool Feasible = SimplifiedVal.isZeroConstant() != Assumption;
29+
return Feasible ? State : nullptr;
30+
}
31+
32+
if (SymbolRef SimplifiedSym = SimplifiedVal.getAsSymbol())
33+
Sym = SimplifiedSym;
2734

2835
// Handle SymbolData.
2936
if (isa<SymbolData>(Sym))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_analyze_cc1 -triple=x86_64-unknown-linux-gnu %s \
2+
// RUN: -analyzer-checker=debug.ExprInspection \
3+
// RUN: -verify
4+
5+
void clang_analyzer_eval(int);
6+
void clang_analyzer_value(int);
7+
8+
void test_derived_sym_simplification_on_assume(int s0, int s1) {
9+
int elem = s0 + s1 + 1;
10+
if (elem-- == 0)
11+
return;
12+
13+
if (elem-- == 0)
14+
return;
15+
16+
if (s0 < 1)
17+
return;
18+
clang_analyzer_value(s0); // expected-warning{{[1, 2147483647]}}
19+
20+
if (s1 < 1)
21+
return;
22+
clang_analyzer_value(s1); // expected-warning{{[1, 2147483647]}}
23+
24+
clang_analyzer_eval(elem); // expected-warning{{UNKNOWN}}
25+
if (elem-- == 0)
26+
return;
27+
28+
if (s0 > 1)
29+
return;
30+
clang_analyzer_eval(s0 == 1); // expected-warning{{TRUE}}
31+
32+
if (s1 > 1)
33+
return;
34+
clang_analyzer_eval(s1 == 1); // expected-warning{{TRUE}}
35+
36+
clang_analyzer_eval(elem); // expected-warning{{FALSE}}
37+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %clang_analyze_cc1 %s \
2+
// RUN: -analyzer-max-loop 6 \
3+
// RUN: -analyzer-checker=unix.StdCLibraryFunctions \
4+
// RUN: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \
5+
// RUN: -analyzer-checker=debug.ExprInspection \
6+
// RUN: -triple x86_64-unknown-linux-gnu \
7+
// RUN: -verify
8+
9+
#include "Inputs/std-c-library-functions-POSIX.h"
10+
11+
void clang_analyzer_value(int);
12+
void clang_analyzer_warnIfReached();
13+
void clang_analyzer_printState();
14+
15+
void _add_one_to_index_C(int *indices, int *shape) {
16+
int k = 1;
17+
for (; k >= 0; k--)
18+
if (indices[k] < shape[k])
19+
indices[k]++;
20+
else
21+
indices[k] = 0;
22+
}
23+
24+
void PyObject_CopyData_sptr(char *i, char *j, int *indices, int itemsize,
25+
int *shape, struct sockaddr *restrict sa) {
26+
int elements = 1;
27+
for (int k = 0; k < 2; k++)
28+
elements += shape[k];
29+
30+
// no contradiction after 3 iterations when 'elements' could be
31+
// simplified to 0
32+
int iterations = 0;
33+
while (elements--) {
34+
iterations++;
35+
_add_one_to_index_C(indices, shape);
36+
getnameinfo(sa, 10, i, itemsize, i, itemsize, 0); // no crash here
37+
}
38+
39+
if (shape[0] == 1 && shape[1] == 1 && indices[0] == 0 && indices[1] == 0) {
40+
clang_analyzer_value(iterations == 3 && elements == -1);
41+
// expected-warning@-1{{1}}
42+
}
43+
}

clang/test/Analysis/symbol-simplification-fixpoint-two-iterations.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ void test(int a, int b, int c, int d) {
2828
return;
2929
clang_analyzer_printState();
3030
// CHECK: "constraints": [
31-
// CHECK-NEXT: { "symbol": "(reg_$0<int a>) != (reg_$3<int d>)", "range": "{ [0, 0] }" },
31+
// CHECK-NEXT: { "symbol": "((reg_$0<int a>) + (reg_$2<int c>)) != (reg_$3<int d>)", "range": "{ [0, 0] }" },
3232
// CHECK-NEXT: { "symbol": "reg_$1<int b>", "range": "{ [0, 0] }" },
3333
// CHECK-NEXT: { "symbol": "reg_$2<int c>", "range": "{ [0, 0] }" }
3434
// CHECK-NEXT: ],
3535
// CHECK-NEXT: "equivalence_classes": [
36-
// CHECK-NEXT: [ "(reg_$0<int a>) != (reg_$3<int d>)" ],
37-
// CHECK-NEXT: [ "reg_$0<int a>", "reg_$3<int d>" ],
36+
// CHECK-NEXT: [ "((reg_$0<int a>) + (reg_$2<int c>)) != (reg_$3<int d>)" ],
37+
// CHECK-NEXT: [ "(reg_$0<int a>) + (reg_$2<int c>)", "reg_$3<int d>" ],
3838
// CHECK-NEXT: [ "reg_$2<int c>" ]
3939
// CHECK-NEXT: ],
4040
// CHECK-NEXT: "disequality_info": null,

0 commit comments

Comments
 (0)