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;
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();
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.
.Case("strcmp", &CStringChecker::evalStrcmp)
.Case("strncmp", &CStringChecker::evalStrncmp)
.Case("strcasecmp", &CStringChecker::evalStrcasecmp)
+ .Case("strncasecmp", &CStringChecker::evalStrncasecmp)
.Case("bcopy", &CStringChecker::evalBcopy)
.Default(NULL);
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
+}