Hi,
The following patch makes the VLA size checker detect and warn about
code like:
int i = -4;
char array[i];
The old behavior was to silently convert it to a size_t.
Best regards,
Daniel Fahlgren
Index: lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp (revision 210243)
+++ lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp (working copy)
@@ -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_Kind Kind,
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,16 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *
// declared. We do this by multiplying the array length by the element size,
// then matching that with the array region's extent symbol.
+ SValBuilder &svalBuilder = C.getSValBuilder();
+
+ // Check if the length is negative
+ const llvm::APSInt *KnownInt = svalBuilder.getKnownValue(state, sizeD);
+ if (KnownInt && KnownInt->isSigned() && KnownInt->isNegative()) {
+ reportBug(VLA_Negative, SE, state, C);
+ return;
+ }
+
// Convert the array length to size_t.
- SValBuilder &svalBuilder = C.getSValBuilder();
QualType SizeTy = Ctx.getSizeType();
NonLoc ArrayLength =
svalBuilder.evalCast(sizeD, SizeTy, SE->getType()).castAs<NonLoc>();
Index: test/Analysis/misc-ps.m
===================================================================
--- test/Analysis/misc-ps.m (revision 210243)
+++ test/Analysis/misc-ps.m (working copy)
@@ -131,6 +131,58 @@ void check_uninit_sized_VLA() {
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 = -3;
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+void check_negative_sized_VLA_6() {
+ unsigned char x = -3;
+ 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 - 3]; // expected-warning{{Declared variable-length array (VLA) has negative size}}
+}
+
+void check_negative_sized_VLA_9() {
+ int x = 1;
+ int vla[x]; // no-warning
+}
+
// sizeof(void)
// - Tests a regression reported in PR 3211: http://llvm.org/bugs/show_bug.cgi?id=3211
void handle_sizeof_void(unsigned flag) {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits