]> granicus.if.org Git - clang/commitdiff
Implements strncasecmp() checker and simplifies some of the logic around creating...
authorLenny Maiorani <lenny@colorado.edu>
Mon, 2 May 2011 19:05:49 +0000 (19:05 +0000)
committerLenny Maiorani <lenny@colorado.edu>
Mon, 2 May 2011 19:05:49 +0000 (19:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130708 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/CStringChecker.cpp
test/Analysis/string.c

index a6a256a87bcf1330ecc5fa887203d023582e9569..4f9c641edfd6793884df55acfae86125f58cbf19 100644 (file)
@@ -77,6 +77,7 @@ public:
   void evalStrcmp(CheckerContext &C, const CallExpr *CE) const;
   void evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
   void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const;
+  void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const;
   void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
                         bool isBounded = false, bool ignoreCase = false) const;
 
@@ -1128,6 +1129,12 @@ void CStringChecker::evalStrcasecmp(CheckerContext &C,
   evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true);
 }
 
+void CStringChecker::evalStrncasecmp(CheckerContext &C, 
+                                     const CallExpr *CE) const {
+  //int strncasecmp(const char *restrict s1, const char *restrict s2, size_t n);
+  evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true);
+}
+
 void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
                                       bool isBounded, bool ignoreCase) const {
   const GRState *state = C.getState();
@@ -1181,31 +1188,17 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
       return;
     llvm::APSInt lenInt(CI->getValue());
 
-    // Compare using the bounds provided like strncmp() does.
-    if (ignoreCase) {
-      // TODO Implement compare_lower(RHS, n) in LLVM StringRef.
-      // result = s1StrRef.compare_lower(s2StrRef, 
-      //                                 (size_t)lenInt.getLimitedValue());
+    // Create substrings of each to compare the prefix.
+    s1StrRef = s1StrRef.substr(0, (size_t)lenInt.getLimitedValue());
+    s2StrRef = s2StrRef.substr(0, (size_t)lenInt.getLimitedValue());
+  }
 
-      // For now, give up.
-      return;
-    } else {
-      // Create substrings of each to compare the prefix.
-      llvm::StringRef s1SubStr = 
-        s1StrRef.substr(0, (size_t)lenInt.getLimitedValue());
-      llvm::StringRef s2SubStr = 
-        s2StrRef.substr(0, (size_t)lenInt.getLimitedValue());
-
-      // Compare the substrings.
-      result = s1SubStr.compare(s2SubStr);
-    }
+  if (ignoreCase) {
+    // Compare string 1 to string 2 the same way strcasecmp() does.
+    result = s1StrRef.compare_lower(s2StrRef);
   } else {
     // Compare string 1 to string 2 the same way strcmp() does.
-    if (ignoreCase) {
-      result = s1StrRef.compare_lower(s2StrRef);
-    } else {
-      result = s1StrRef.compare(s2StrRef);
-    }
+    result = s1StrRef.compare(s2StrRef);
   }
   
   // Build the SVal of the comparison to bind the return value.
@@ -1256,6 +1249,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
     .Case("strcmp", &CStringChecker::evalStrcmp)
     .Case("strncmp", &CStringChecker::evalStrncmp)
     .Case("strcasecmp", &CStringChecker::evalStrcasecmp)
+    .Case("strncasecmp", &CStringChecker::evalStrncasecmp)
     .Case("bcopy", &CStringChecker::evalBcopy)
     .Default(NULL);
 
index 19c838c255646becf097940b40d2887f4de3df83..40afacc4388e242830c6d1c3ef57039763c21aab 100644 (file)
@@ -872,3 +872,109 @@ void strcasecmp_diff_length_3() {
   if (strcasecmp(x, y) != -1)
     (void)*(char*)0; // no-warning
 }
+
+//===----------------------------------------------------------------------===
+// strncasecmp()
+//===----------------------------------------------------------------------===
+
+#define strncasecmp BUILTIN(strncasecmp)
+int strncasecmp(const char *restrict s1, const char *restrict s2, size_t n);
+
+void strncasecmp_constant0() {
+  if (strncasecmp("abc", "Abc", 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_constant_and_var_0() {
+  char *x = "abc";
+  if (strncasecmp(x, "Abc", 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_constant_and_var_1() {
+  char *x = "abc";
+  if (strncasecmp("Abc", x, 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_0() {
+  char *x = "abc";
+  char *y = "Abc";
+  if (strncasecmp(x, y, 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_1() {
+  char *x = "Bcd";
+  char *y = "abc";
+  if (strncasecmp(x, y, 3) != 1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_2() {
+  char *x = "abc";
+  char *y = "Bcd";
+  if (strncasecmp(x, y, 3) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_null_0() {
+  char *x = NULL;
+  char *y = "123";
+  strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strncasecmp_null_1() {
+  char *x = "123";
+  char *y = NULL;
+  strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strncasecmp_diff_length_0() {
+  char *x = "abcde";
+  char *y = "aBd";
+  if (strncasecmp(x, y, 5) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_diff_length_1() {
+  char *x = "abc";
+  char *y = "aBdef";
+  if (strncasecmp(x, y, 5) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_diff_length_2() {
+  char *x = "aBcDe";
+  char *y = "abc";
+  if (strncasecmp(x, y, 5) != 1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_diff_length_3() {
+  char *x = "aBc";
+  char *y = "abcde";
+  if (strncasecmp(x, y, 5) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_diff_length_4() {
+  char *x = "abcde";
+  char *y = "aBc";
+  if (strncasecmp(x, y, 3) != 0)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_diff_length_5() {
+  char *x = "abcde";
+  char *y = "aBd";
+  if (strncasecmp(x, y, 3) != -1)
+    (void)*(char*)0; // no-warning
+}
+
+void strncasecmp_diff_length_6() {
+  char *x = "aBDe";
+  char *y = "abc";
+  if (strncasecmp(x, y, 3) != 1)
+    (void)*(char*)0; // no-warning
+}