r215456 - [analyzer] Check for negative values used as the size of a C variable-length array.
Jordan Rose
jordan_rose at apple.com
Tue Aug 12 09:44:22 PDT 2014
Author: jrose
Date: Tue Aug 12 11:44:22 2014
New Revision: 215456
URL: http://llvm.org/viewvc/llvm-project?rev=215456&view=rev
Log:
[analyzer] Check for negative values used as the size of a C variable-length array.
Patch by Daniel Fahlgren!
Added:
cfe/trunk/test/Analysis/vla.c
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
cfe/trunk/test/Analysis/misc-ps.m
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp?rev=215456&r1=215455&r2=215456&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp Tue Aug 12 11:44:22 2014
@@ -30,7 +30,7 @@ using namespace ento;
namespace {
class VLASizeChecker : public Checker< check::PreStmt<DeclStmt> > {
mutable std::unique_ptr<BugType> BT;
- enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Tainted };
+ enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Tainted, VLA_Negative };
void reportBug(VLASize_Kind Kind,
const Expr *SizeE,
@@ -67,6 +67,9 @@ void VLASizeChecker::reportBug(VLASize_K
case VLA_Tainted:
os << "has tainted size";
break;
+ case VLA_Negative:
+ os << "has negative size";
+ break;
}
BugReport *report = new BugReport(*BT, os.str(), N);
@@ -128,8 +131,27 @@ void VLASizeChecker::checkPreStmt(const
// declared. We do this by multiplying the array length by the element size,
// then matching that with the array region's extent symbol.
- // Convert the array length to size_t.
+ // Check if the size is negative.
SValBuilder &svalBuilder = C.getSValBuilder();
+
+ QualType Ty = SE->getType();
+ DefinedOrUnknownSVal Zero = svalBuilder.makeZeroVal(Ty);
+
+ SVal LessThanZeroVal = svalBuilder.evalBinOp(state, BO_LT, sizeD, Zero, Ty);
+ if (Optional<DefinedSVal> LessThanZeroDVal =
+ LessThanZeroVal.getAs<DefinedSVal>()) {
+ ConstraintManager &CM = C.getConstraintManager();
+ ProgramStateRef StatePos, StateNeg;
+
+ std::tie(StateNeg, StatePos) = CM.assumeDual(state, *LessThanZeroDVal);
+ if (StateNeg && !StatePos) {
+ reportBug(VLA_Negative, SE, state, C);
+ return;
+ }
+ state = StatePos;
+ }
+
+ // Convert the array length to size_t.
QualType SizeTy = Ctx.getSizeType();
NonLoc ArrayLength =
svalBuilder.evalCast(sizeD, SizeTy, SE->getType()).castAs<NonLoc>();
Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=215456&r1=215455&r2=215456&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Tue Aug 12 11:44:22 2014
@@ -118,19 +118,6 @@ __m128i vec128i(long long __q1, long lon
return __extension__ (__m128i)(__v2di){ __q0, __q1 };
}
-// Zero-sized VLAs.
-void check_zero_sized_VLA(int x) {
- if (x)
- return;
-
- int vla[x]; // expected-warning{{Declared variable-length array (VLA) has zero size}}
-}
-
-void check_uninit_sized_VLA() {
- int x;
- int vla[x]; // expected-warning{{Declared variable-length array (VLA) uses a garbage value as its size}}
-}
-
// sizeof(void)
// - Tests a regression reported in PR 3211: http://llvm.org/bugs/show_bug.cgi?id=3211
void handle_sizeof_void(unsigned flag) {
Added: cfe/trunk/test/Analysis/vla.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/vla.c?rev=215456&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/vla.c (added)
+++ cfe/trunk/test/Analysis/vla.c Tue Aug 12 11:44:22 2014
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s
+
+// Zero-sized VLAs.
+void check_zero_sized_VLA(int x) {
+ if (x)
+ return;
+
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has zero size}}
+}
+
+void check_uninit_sized_VLA() {
+ int x;
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) uses a garbage value as its size}}
+}
+
+// Negative VLAs.
+static void vla_allocate_signed(int x) {
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+static void vla_allocate_unsigned(unsigned int x) {
+ int vla[x]; // no-warning
+}
+
+void check_negative_sized_VLA_1() {
+ vla_allocate_signed(-1);
+}
+
+void check_negative_sized_VLA_2() {
+ vla_allocate_unsigned(-1);
+}
+
+void check_negative_sized_VLA_3() {
+ int x = -1;
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+void check_negative_sized_VLA_4() {
+ unsigned int x = -1;
+ int vla[x]; // no-warning
+}
+
+void check_negative_sized_VLA_5() {
+ signed char x = -1;
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+void check_negative_sized_VLA_6() {
+ unsigned char x = -1;
+ int vla[x]; // no-warning
+}
+
+void check_negative_sized_VLA_7() {
+ signed char x = -1;
+ int vla[x + 2]; // no-warning
+}
+
+void check_negative_sized_VLA_8() {
+ signed char x = 1;
+ int vla[x - 2]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+void check_negative_sized_VLA_9() {
+ int x = 1;
+ int vla[x]; // no-warning
+}
+
+static void check_negative_sized_VLA_10_sub(int x)
+{
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+void check_negative_sized_VLA_10(int x) {
+ if (x < 0)
+ check_negative_sized_VLA_10_sub(x);
+}
+
+static void check_negative_sized_VLA_11_sub(int x)
+{
+ int vla[x]; // no-warning
+}
+
+void check_negative_sized_VLA_11(int x) {
+ if (x > 0)
+ check_negative_sized_VLA_11_sub(x);
+}
More information about the cfe-commits
mailing list