Skip to content

Commit ad1b2a8

Browse files
authored
[analyzer] Demonstrate superfluous unsigned >= 0 assumption (#78442)
This commit adds a testcase which highlights the current incorrect behavior of the CSA diagnostic generation: it produces a note which says "Assuming 'arg' is >= 0" in a situation where this is not a fresh assumption because 'arg' is an unsigned integer. I also created ticket 78440 to track this bug.
1 parent 1fd1f4c commit ad1b2a8

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,6 +2883,16 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
28832883
// previous program state we assuming the newly seen constraint information.
28842884
// If we cannot evaluate the condition (and the constraints are the same)
28852885
// the analyzer has no information about the value and just assuming it.
2886+
// FIXME: This logic is not entirely correct, because e.g. in code like
2887+
// void f(unsigned arg) {
2888+
// if (arg >= 0) {
2889+
// // ...
2890+
// }
2891+
// }
2892+
// it will say that the "arg >= 0" check is _assuming_ something new because
2893+
// the constraint that "$arg >= 0" is 1 was added to the list of known
2894+
// constraints. However, the unsigned value is always >= 0 so semantically
2895+
// this is not a "real" assumption.
28862896
bool IsAssuming =
28872897
!BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
28882898
CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-output=text \
2+
// RUN: -analyzer-checker=core -verify %s
3+
4+
int assuming_unsigned_ge_0(unsigned arg) {
5+
// TODO This testcase demonstrates the current incorrect behavior of Clang
6+
// Static Analyzer: here 'arg' is unsigned, so "arg >= 0" is not a fresh
7+
// assumption, but it still appears in the diagnostics as if it's fresh:
8+
// expected-note@+2 {{Assuming 'arg' is >= 0}}
9+
// expected-note@+1 {{Taking false branch}}
10+
if (arg < 0)
11+
return 0;
12+
// expected-note@+2 {{Assuming 'arg' is <= 0}}
13+
// expected-note@+1 {{Taking false branch}}
14+
if (arg > 0)
15+
return 0;
16+
// expected-note@+2 {{Division by zero}}
17+
// expected-warning@+1 {{Division by zero}}
18+
return 100 / arg;
19+
}

0 commit comments

Comments
 (0)