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 cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits