diff options
author | Lenny Maiorani <lenny@colorado.edu> | 2011-04-28 15:09:11 +0000 |
---|---|---|
committer | Lenny Maiorani <lenny@colorado.edu> | 2011-04-28 15:09:11 +0000 |
commit | bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3 (patch) | |
tree | 92d56683b5512d9e14c3566d0d929e5211102f4b /lib/StaticAnalyzer/Checkers/CStringChecker.cpp | |
parent | 75c4064932d481ac710a80aa88b3370ad8a6af1d (diff) |
Implements strcasecmp() checker in Static Analyzer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130398 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 1d25680f07..8e9c7899b0 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -76,8 +76,9 @@ 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 evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, - bool isBounded = false) const; + bool isBounded = false, bool ignoreCase = false) const; // Utility methods std::pair<const GRState*, const GRState*> @@ -1106,16 +1107,22 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, void CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { //int strcmp(const char *restrict s1, const char *restrict s2); - evalStrcmpCommon(C, CE, /* isBounded = */ false); + evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ 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); + evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false); +} + +void CStringChecker::evalStrcasecmp(CheckerContext &C, + const CallExpr *CE) const { + //int strcasecmp(const char *restrict s1, const char *restrict s2); + evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true); } void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, - bool isBounded) const { + bool isBounded, bool ignoreCase) const { const GRState *state = C.getState(); // Check that the first string is non-null @@ -1168,10 +1175,23 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, llvm::APSInt lenInt(CI->getValue()); // Compare using the bounds provided like strncmp() does. - result = s1StrRef.compare(s2StrRef, (size_t)lenInt.getLimitedValue()); + if (ignoreCase) { + // TODO Implement compare_lower(RHS, n) in LLVM StringRef. + // result = s1StrRef.compare_lower(s2StrRef, + // (size_t)lenInt.getLimitedValue()); + + // For now, give up. + return; + } else { + result = s1StrRef.compare(s2StrRef, (size_t)lenInt.getLimitedValue()); + } } else { // Compare string 1 to string 2 the same way strcmp() does. - result = s1StrRef.compare(s2StrRef); + if (ignoreCase) { + result = s1StrRef.compare_lower(s2StrRef); + } else { + result = s1StrRef.compare(s2StrRef); + } } // Build the SVal of the comparison to bind the return value. @@ -1221,6 +1241,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { .Case("strnlen", &CStringChecker::evalstrnLength) .Case("strcmp", &CStringChecker::evalStrcmp) .Case("strncmp", &CStringChecker::evalStrncmp) + .Case("strcasecmp", &CStringChecker::evalStrcasecmp) .Case("bcopy", &CStringChecker::evalBcopy) .Default(NULL); |