diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 48 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp | 20 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 11 |
3 files changed, 72 insertions, 7 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 639dd72e9d1..9eb7edffe6d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -982,6 +982,9 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + // void *memcpy(void *restrict dst, const void *restrict src, size_t n); // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); @@ -991,6 +994,9 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); // The return value is a pointer to the byte following the last written byte. const Expr *Dest = CE->getArg(0); @@ -1000,6 +1006,9 @@ void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + // void *memmove(void *dst, const void *src, size_t n); // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); @@ -1009,12 +1018,18 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + // void bcopy(const void *src, void *dst, size_t n); evalCopyCommon(C, CE, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0)); } void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + // int memcmp(const void *s1, const void *s2, size_t n); CurrentFunctionDescription = "memory comparison function"; @@ -1089,12 +1104,18 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 1) + return; + // size_t strlen(const char *s); evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); } void CStringChecker::evalstrnLength(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 2) + return; + // size_t strnlen(const char *s, size_t maxlen); evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); } @@ -1225,6 +1246,9 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, } void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 2) + return; + // char *strcpy(char *restrict dst, const char *restrict src); evalStrcpyCommon(C, CE, /* returnEnd = */ false, @@ -1233,6 +1257,9 @@ void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + // char *strncpy(char *restrict dst, const char *restrict src, size_t n); evalStrcpyCommon(C, CE, /* returnEnd = */ false, @@ -1241,6 +1268,9 @@ void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 2) + return; + // char *stpcpy(char *restrict dst, const char *restrict src); evalStrcpyCommon(C, CE, /* returnEnd = */ true, @@ -1249,6 +1279,9 @@ void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 2) + return; + //char *strcat(char *restrict s1, const char *restrict s2); evalStrcpyCommon(C, CE, /* returnEnd = */ false, @@ -1257,6 +1290,9 @@ void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { } void CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + //char *strncat(char *restrict s1, const char *restrict s2, size_t n); evalStrcpyCommon(C, CE, /* returnEnd = */ false, @@ -1568,23 +1604,35 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, } void CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 2) + return; + //int strcmp(const char *s1, const char *s2); evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false); } void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + //int strncmp(const char *s1, const char *s2, size_t n); evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false); } void CStringChecker::evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 2) + return; + //int strcasecmp(const char *s1, const char *s2); evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true); } void CStringChecker::evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const { + if (CE->getNumArgs() < 3) + return; + //int strncasecmp(const char *s1, const char *s2, size_t n); evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true); } diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index 4490ddbcc0c..135b81dda4a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -350,6 +350,8 @@ bool GenericTaintChecker::propagateFromPre(const CallExpr *CE, // The arguments are pointer arguments. The data they are pointing at is // tainted after the call. + if (CE->getNumArgs() < (ArgNum + 1)) + return false; const Expr* Arg = CE->getArg(ArgNum); SymbolRef Sym = getPointedToSymbol(C, Arg); if (Sym) @@ -458,7 +460,8 @@ GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE, break; } - assert(ArgNum < CE->getNumArgs()); + if (CE->getNumArgs() < (ArgNum + 1)) + return State; if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C))) break; } @@ -525,9 +528,10 @@ ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE, // If argument 0(protocol domain) is network, the return value should get taint. ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE, - CheckerContext &C) const { - assert(CE->getNumArgs() >= 3); + CheckerContext &C) const { ProgramStateRef State = C.getState(); + if (CE->getNumArgs() < 3) + return State; SourceLocation DomLoc = CE->getArg(0)->getExprLoc(); StringRef DomName = C.getMacroNameOrSpelling(DomLoc); @@ -542,7 +546,9 @@ ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE, ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE, CheckerContext &C) const { ProgramStateRef State = C.getState(); - assert(CE->getNumArgs() >= 2); + if (CE->getNumArgs() < 2) + return State; + SVal x = State->getSVal(CE->getArg(1), C.getLocationContext()); // All arguments except for the very first one should get taint. for (unsigned int i = 1; i < CE->getNumArgs(); ++i) { @@ -557,7 +563,7 @@ ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE, } ProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE, - CheckerContext &C) const { + CheckerContext &C) const { return C.getState()->addTaint(CE, C.getLocationContext()); } @@ -677,7 +683,7 @@ bool GenericTaintChecker::checkSystemCall(const CallExpr *CE, .Case("dlopen", 0) .Default(UINT_MAX); - if (ArgNum == UINT_MAX) + if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1)) return false; if (generateReportIfTainted(CE->getArg(ArgNum), @@ -722,7 +728,7 @@ bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE, ArgNum = 2; } - if (ArgNum != InvalidArgIndex && + if (ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum && generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C)) return true; diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 7456af23441..8bce88a7697 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -368,6 +368,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { ProgramStateRef State = C.getState(); if (FunI == II_malloc || FunI == II_valloc) { + if (CE->getNumArgs() < 1) + return; State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); } else if (FunI == II_realloc) { State = ReallocMem(C, CE, false); @@ -490,6 +492,9 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, ProgramStateRef state, unsigned Num, bool Hold) const { + if (CE->getNumArgs() < (Num + 1)) + return 0; + const Expr *ArgExpr = CE->getArg(Num); SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext()); if (!isa<DefinedOrUnknownSVal>(ArgVal)) @@ -710,6 +715,9 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE, bool FreesOnFail) const { + if (CE->getNumArgs() < 2) + return 0; + ProgramStateRef state = C.getState(); const Expr *arg0Expr = CE->getArg(0); const LocationContext *LCtx = C.getLocationContext(); @@ -795,6 +803,9 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C, } ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){ + if (CE->getNumArgs() < 2) + return 0; + ProgramStateRef state = C.getState(); SValBuilder &svalBuilder = C.getSValBuilder(); const LocationContext *LCtx = C.getLocationContext(); |