Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -661,7 +661,7 @@ if (Recorded) return *Recorded; } - + // Otherwise, get a new symbol and update the state. SValBuilder &svalBuilder = C.getSValBuilder(); QualType sizeTy = svalBuilder.getContext().getSizeType(); @@ -669,8 +669,20 @@ MR, Ex, sizeTy, C.blockCount()); - if (!hypothetical) + if (!hypothetical) { + // In case of unbounded calls strlen etc bound the range to SIZE_MAX/4 + BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); + const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy); + llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4); + const llvm::APSInt* maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt, fourInt); + NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt); + if (Optional strLn = strLength.getAs()) { + SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn, + maxLength, sizeTy); + state = state->assume(evalLength.castAs(), true); + } state = state->set(MR, strLength); + } return strLength; } Index: test/Analysis/pr16558.c =================================================================== --- test/Analysis/pr16558.c +++ test/Analysis/pr16558.c @@ -0,0 +1,38 @@ +//RUN: %clang_cc1 -analyze -analyzer-checker=core,unix -verify %s + +typedef typeof(sizeof(int)) size_t; +extern void* malloc (size_t size); +size_t strlen(const char *s); +char *strcpy(char *restrict s1, const char *restrict s2); + +void *smallocNoWarn(size_t size) { + if (size == 0) { + return malloc(1); // this branch is never called + } + else { + return malloc(size); + } +} + +char *dupstrNoWarn(const char *s) { + const int len = strlen(s); + char *p = (char*) smallocNoWarn(len + 1); + strcpy(p, s); // no-warning + return p; +} + +void *smallocWarn(size_t size) { + if (size == 2) { + return malloc(1); + } + else { + return malloc(size); + } +} + +char *dupstrWarn(const char *s) { + const int len = strlen(s); + char *p = (char*) smallocWarn(len + 1); + strcpy(p, s); // expected-warning{{String copy function overflows destination buffer}} + return p; +} Index: test/Analysis/string.c =================================================================== --- test/Analysis/string.c +++ test/Analysis/string.c @@ -23,7 +23,6 @@ #else /* USE_BUILTINS */ # define BUILTIN(f) f #endif /* USE_BUILTINS */ - #define NULL 0 typedef typeof(sizeof(int)) size_t; @@ -434,7 +433,7 @@ return; if (strlen(src) != 2) return; - strcat(dst, src); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}} + strcat(dst, src); } @@ -657,7 +656,7 @@ return; if (strlen(src) != 2) return; - strncat(dst, src, 2); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}} + strncat(dst, src, 2); } void strncat_zero(char *src) {