const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
bool canComputeResult = false;
+ SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx,
+ C.blockCount());
if (s1StrLiteral && s2StrLiteral) {
StringRef s1StrRef = s1StrLiteral->getString();
s2StrRef = s2StrRef.substr(0, s2Term);
// Use StringRef's comparison methods to compute the actual result.
- int result;
+ int compareRes = ignoreCase ? s1StrRef.compare_lower(s2StrRef)
+ : s1StrRef.compare(s2StrRef);
- 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.
- result = s1StrRef.compare(s2StrRef);
+ // The strcmp function returns an integer greater than, equal to, or less
+ // than zero, [c11, p7.24.4.2].
+ if (compareRes == 0) {
+ resultVal = svalBuilder.makeIntVal(compareRes, CE->getType());
+ }
+ else {
+ DefinedSVal zeroVal = svalBuilder.makeIntVal(0, CE->getType());
+ // Constrain strcmp's result range based on the result of StringRef's
+ // comparison methods.
+ BinaryOperatorKind op = (compareRes == 1) ? BO_GT : BO_LT;
+ SVal compareWithZero =
+ svalBuilder.evalBinOp(state, op, resultVal, zeroVal,
+ svalBuilder.getConditionType());
+ DefinedSVal compareWithZeroVal = compareWithZero.castAs<DefinedSVal>();
+ state = state->assume(compareWithZeroVal, true);
}
-
- // Build the SVal of the comparison and bind the return value.
- SVal resultVal = svalBuilder.makeIntVal(result, CE->getType());
- state = state->BindExpr(CE, LCtx, resultVal);
}
}
- if (!canComputeResult) {
- // Conjure a symbolic value. It's the best we can do.
- SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx,
- C.blockCount());
- state = state->BindExpr(CE, LCtx, resultVal);
- }
+ state = state->BindExpr(CE, LCtx, resultVal);
// Record this as a possible path.
C.addTransition(state);
#define strcmp BUILTIN(strcmp)
int strcmp(const char * s1, const char * s2);
+void strcmp_check_modelling() {
+ char *x = "aa";
+ char *y = "a";
+ clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) <= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strcmp(x, y) > 1); // expected-warning{{UNKNOWN}}
+
+ clang_analyzer_eval(strcmp(y, x) < 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(y, x) >= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strcmp(y, x) < -1); // expected-warning{{UNKNOWN}}
+}
+
void strcmp_constant0() {
clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}}
}
void strcmp_1() {
char *x = "234";
char *y = "123";
- clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
}
void strcmp_2() {
char *x = "123";
char *y = "234";
- clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcmp_null_0() {
void strcmp_diff_length_0() {
char *x = "12345";
char *y = "234";
- clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcmp_diff_length_1() {
char *x = "123";
char *y = "23456";
- clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcmp_diff_length_2() {
char *x = "12345";
char *y = "123";
- clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
}
void strcmp_diff_length_3() {
char *x = "123";
char *y = "12345";
- clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcmp_embedded_null () {
#define strncmp BUILTIN(strncmp)
int strncmp(const char *s1, const char *s2, size_t n);
+void strncmp_check_modelling() {
+ char *x = "aa";
+ char *y = "a";
+ clang_analyzer_eval(strncmp(x, y, 2) > 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 2) <= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strncmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}}
+
+ clang_analyzer_eval(strncmp(y, x, 2) < 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(y, x, 2) >= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strncmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}}
+}
+
void strncmp_constant0() {
clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}}
}
void strncmp_1() {
char *x = "234";
char *y = "123";
- clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}}
}
void strncmp_2() {
char *x = "123";
char *y = "234";
- clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}}
}
void strncmp_null_0() {
void strncmp_diff_length_0() {
char *x = "12345";
char *y = "234";
- clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
}
void strncmp_diff_length_1() {
char *x = "123";
char *y = "23456";
- clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
}
void strncmp_diff_length_2() {
char *x = "12345";
char *y = "123";
- clang_analyzer_eval(strncmp(x, y, 5) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 5) > 0); // expected-warning{{TRUE}}
}
void strncmp_diff_length_3() {
char *x = "123";
char *y = "12345";
- clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
}
void strncmp_diff_length_4() {
void strncmp_diff_length_5() {
char *x = "012";
char *y = "12345";
- clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}}
}
void strncmp_diff_length_6() {
char *x = "234";
char *y = "12345";
- clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}}
}
void strncmp_embedded_null () {
#define strcasecmp BUILTIN(strcasecmp)
int strcasecmp(const char *s1, const char *s2);
+void strcasecmp_check_modelling() {
+ char *x = "aa";
+ char *y = "a";
+ clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) <= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strcasecmp(x, y) > 1); // expected-warning{{UNKNOWN}}
+
+ clang_analyzer_eval(strcasecmp(y, x) < 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(y, x) >= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strcasecmp(y, x) < -1); // expected-warning{{UNKNOWN}}
+}
+
void strcasecmp_constant0() {
clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}}
}
void strcasecmp_1() {
char *x = "Bcd";
char *y = "abc";
- clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
}
void strcasecmp_2() {
char *x = "abc";
char *y = "Bcd";
- clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcasecmp_null_0() {
void strcasecmp_diff_length_0() {
char *x = "abcde";
char *y = "aBd";
- clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcasecmp_diff_length_1() {
char *x = "abc";
char *y = "aBdef";
- clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcasecmp_diff_length_2() {
char *x = "aBcDe";
char *y = "abc";
- clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
}
void strcasecmp_diff_length_3() {
char *x = "aBc";
char *y = "abcde";
- clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
}
void strcasecmp_embedded_null () {
#define strncasecmp BUILTIN(strncasecmp)
int strncasecmp(const char *s1, const char *s2, size_t n);
+void strncasecmp_check_modelling() {
+ char *x = "aa";
+ char *y = "a";
+ clang_analyzer_eval(strncasecmp(x, y, 2) > 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 2) <= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strncasecmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}}
+
+ clang_analyzer_eval(strncasecmp(y, x, 2) < 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(y, x, 2) >= 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(strncasecmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}}
+}
+
void strncasecmp_constant0() {
clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}}
}
void strncasecmp_1() {
char *x = "Bcd";
char *y = "abc";
- clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}}
}
void strncasecmp_2() {
char *x = "abc";
char *y = "Bcd";
- clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}}
}
void strncasecmp_null_0() {
void strncasecmp_diff_length_0() {
char *x = "abcde";
char *y = "aBd";
- clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_1() {
char *x = "abc";
char *y = "aBdef";
- clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_2() {
char *x = "aBcDe";
char *y = "abc";
- clang_analyzer_eval(strncasecmp(x, y, 5) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 5) > 0); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_3() {
char *x = "aBc";
char *y = "abcde";
- clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_4() {
void strncasecmp_diff_length_5() {
char *x = "abcde";
char *y = "aBd";
- clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_6() {
char *x = "aBDe";
char *y = "abc";
- clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}}
}
void strncasecmp_embedded_null () {