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

Reply via email to