[cfe-commits] r130161 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/CStringChecker.cpp test/Analysis/string.c

Lenny Maiorani lenny at colorado.edu
Mon Apr 25 15:21:00 PDT 2011


Author: lenny
Date: Mon Apr 25 17:21:00 2011
New Revision: 130161

URL: http://llvm.org/viewvc/llvm-project?rev=130161&view=rev
Log:
Implements the strncmp() checker just like the strcmp() checker, but with bounds. Requires LLVM svn r129582.


Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    cfe/trunk/test/Analysis/string.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=130161&r1=130160&r2=130161&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Mon Apr 25 17:21:00 2011
@@ -75,6 +75,9 @@
   void evalStrncat(CheckerContext &C, const CallExpr *CE) const;
 
   void evalStrcmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
+                        bool isBounded = false) const;
 
   // Utility methods
   std::pair<const GRState*, const GRState*>
@@ -1103,7 +1106,16 @@
 
 void CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const {
   //int strcmp(const char *restrict s1, const char *restrict s2);
+  evalStrcmpCommon(C, CE, /* isBounded = */ false);
+}
+
+void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const {
+  //int strncmp(const char *restrict s1, const char *restrict s2, size_t n);
+  evalStrcmpCommon(C, CE, /* isBounded = */ true);
+}
 
+void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
+                                      bool isBounded) const {
   const GRState *state = C.getState();
 
   // Check that the first string is non-null
@@ -1142,8 +1154,25 @@
     return;
   llvm::StringRef s2StrRef = s2StrLiteral->getString();
 
-  // Compare string 1 to string 2 the same way strcmp() does.
-  int result = s1StrRef.compare(s2StrRef);
+  int result;
+  if (isBounded) {
+    // Get the max number of characters to compare.
+    const Expr *lenExpr = CE->getArg(2);
+    SVal lenVal = state->getSVal(lenExpr);
+
+    // Dynamically cast the length to a ConcreteInt. If it is not a ConcreteInt
+    // then give up, otherwise get the value and use it as the bounds.
+    nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&lenVal);
+    if (!CI)
+      return;
+    llvm::APSInt lenInt(CI->getValue());
+
+    // Compare using the bounds provided like strncmp() does.
+    result = s1StrRef.compare(s2StrRef, (size_t)lenInt.getLimitedValue());
+  } else {
+    // Compare string 1 to string 2 the same way strcmp() does.
+    result = s1StrRef.compare(s2StrRef);
+  }
   
   // Build the SVal of the comparison to bind the return value.
   SValBuilder &svalBuilder = C.getSValBuilder();
@@ -1191,6 +1220,7 @@
     .Case("strlen", &CStringChecker::evalstrLength)
     .Case("strnlen", &CStringChecker::evalstrnLength)
     .Case("strcmp", &CStringChecker::evalStrcmp)
+    .Case("strncmp", &CStringChecker::evalStrncmp)
     .Case("bcopy", &CStringChecker::evalBcopy)
     .Default(NULL);
 

Modified: cfe/trunk/test/Analysis/string.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=130161&r1=130160&r2=130161&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/string.c (original)
+++ cfe/trunk/test/Analysis/string.c Mon Apr 25 17:21:00 2011
@@ -682,3 +682,109 @@
     (void)*(char*)0; // no-warning
 }
 
+//===----------------------------------------------------------------------===
+// strncmp()
+//===----------------------------------------------------------------------===
+
+#define strncmp BUILTIN(strncmp)
+int strncmp(const char *restrict s1, const char *restrict s2, size_t n);
+
+void strncmp_constant0() {
+  if (strncmp("123", "123", 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_constant_and_var_0() {
+  char *x = "123";
+  if (strncmp(x, "123", 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_constant_and_var_1() {
+  char *x = "123";
+  if (strncmp("123", x, 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_0() {
+  char *x = "123";
+  char *y = "123";
+  if (strncmp(x, y, 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_1() {
+  char *x = "234";
+  char *y = "123";
+  if (strncmp(x, y, 3) != 1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_2() {
+  char *x = "123";
+  char *y = "234";
+  if (strncmp(x, y, 3) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_null_0() {
+  char *x = NULL;
+  char *y = "123";
+  strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strncmp_null_1() {
+  char *x = "123";
+  char *y = NULL;
+  strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strncmp_diff_length_0() {
+  char *x = "12345";
+  char *y = "234";
+  if (strncmp(x, y, 5) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_diff_length_1() {
+  char *x = "123";
+  char *y = "23456";
+  if (strncmp(x, y, 5) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_diff_length_2() {
+  char *x = "12345";
+  char *y = "123";
+  if (strncmp(x, y, 5) != 1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_diff_length_3() {
+  char *x = "123";
+  char *y = "12345";
+  if (strncmp(x, y, 5) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_diff_length_4() {
+  char *x = "123";
+  char *y = "12345";
+  if (strncmp(x, y, 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_diff_length_5() {
+  char *x = "012";
+  char *y = "12345";
+  if (strncmp(x, y, 3) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncmp_diff_length_6() {
+  char *x = "234";
+  char *y = "12345";
+  if (strncmp(x, y, 3) != 1)
+    (void)*(char*)0; // no-warning
+}
+





More information about the cfe-commits mailing list