Skip to content

Commit 4b31027

Browse files
committed
[analyzer] Fix core.VLASize checker false positive taint reports
The checker reported a false positive on this code void testTaintedSanitizedVLASize(void) { int x; scanf("%d", &x); if (x<1) return; int vla[x]; // no-warning } After the fix, the checker only emits tainted warning if the vla size is coming from a tainted source and it cannot prove that it is positive.
1 parent 10edd5d commit 4b31027

File tree

3 files changed

+20
-11
lines changed

3 files changed

+20
-11
lines changed

clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,6 @@ ProgramStateRef VLASizeChecker::checkVLAIndexSize(CheckerContext &C,
162162
if (SizeV.isUnknown())
163163
return nullptr;
164164

165-
// Check if the size is tainted.
166-
if (isTainted(State, SizeV)) {
167-
reportTaintBug(SizeE, State, C, SizeV);
168-
return nullptr;
169-
}
170-
171165
// Check if the size is zero.
172166
DefinedSVal SizeD = SizeV.castAs<DefinedSVal>();
173167

@@ -189,10 +183,10 @@ ProgramStateRef VLASizeChecker::checkVLAIndexSize(CheckerContext &C,
189183
DefinedOrUnknownSVal Zero = SVB.makeZeroVal(SizeTy);
190184

191185
SVal LessThanZeroVal = SVB.evalBinOp(State, BO_LT, SizeD, Zero, SizeTy);
186+
ProgramStateRef StatePos, StateNeg;
192187
if (std::optional<DefinedSVal> LessThanZeroDVal =
193188
LessThanZeroVal.getAs<DefinedSVal>()) {
194189
ConstraintManager &CM = C.getConstraintManager();
195-
ProgramStateRef StatePos, StateNeg;
196190

197191
std::tie(StateNeg, StatePos) = CM.assumeDual(State, *LessThanZeroDVal);
198192
if (StateNeg && !StatePos) {
@@ -202,6 +196,12 @@ ProgramStateRef VLASizeChecker::checkVLAIndexSize(CheckerContext &C,
202196
State = StatePos;
203197
}
204198

199+
// Check if the size is tainted.
200+
if ((StateNeg || StateZero) && isTainted(State, SizeV)) {
201+
reportTaintBug(SizeE, State, C, SizeV);
202+
return nullptr;
203+
}
204+
205205
return State;
206206
}
207207

@@ -220,7 +220,7 @@ void VLASizeChecker::reportTaintBug(const Expr *SizeE, ProgramStateRef State,
220220
SmallString<256> buf;
221221
llvm::raw_svector_ostream os(buf);
222222
os << "Declared variable-length array (VLA) ";
223-
os << "has tainted size";
223+
os << "has a tainted (attacker controlled) size, that can be 0 or negative";
224224

225225
auto report = std::make_unique<PathSensitiveBugReport>(*TaintBT, os.str(), N);
226226
report->addRange(SizeE->getSourceRange());

clang/test/Analysis/taint-diagnostic-visitor.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ void taintDiagnosticVLA(void) {
4646
scanf("%d", &x); // expected-note {{Value assigned to 'x'}}
4747
// expected-note@-1 {{Taint originated here}}
4848
// expected-note@-2 {{Taint propagated to the 2nd argument}}
49-
int vla[x]; // expected-warning {{Declared variable-length array (VLA) has tainted size}}
50-
// expected-note@-1 {{Declared variable-length array (VLA) has tainted size}}
49+
int vla[x]; // expected-warning {{Declared variable-length array (VLA) has a tainted}}
50+
// expected-note@-1 {{Declared variable-length array (VLA) has a tainted}}
5151
}
5252

5353

clang/test/Analysis/taint-generic.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,16 @@ int testDivByZero(void) {
405405
void testTaintedVLASize(void) {
406406
int x;
407407
scanf("%d", &x);
408-
int vla[x]; // expected-warning{{Declared variable-length array (VLA) has tainted size}}
408+
int vla[x]; // expected-warning{{Declared variable-length array (VLA) has a tainted (attacker controlled) size, that can be 0 or negative}}
409+
}
410+
411+
// Tainted-sanitized VLAs.
412+
void testTaintedSanitizedVLASize(void) {
413+
int x;
414+
scanf("%d", &x);
415+
if (x<1)
416+
return;
417+
int vla[x]; // no-warning
409418
}
410419

411420
int testTaintedAllocaMem() {

0 commit comments

Comments
 (0)