diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -266,13 +266,16 @@ std::pair CStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V, QualType Ty) { + auto states = std::make_pair(state, state); + + // LazyCompoundVal cannot be handled by assume Optional val = V.getAs(); - if (!val) - return std::pair(state, state); + if (val && !V.getAs()) { + // return pair shall be {null, non-null} so reorder states + std::tie(states.second, states.first) = state->assume(*val); + } - SValBuilder &svalBuilder = C.getSValBuilder(); - DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); - return state->assume(svalBuilder.evalEQ(state, *val, zero)); + return states; } ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C, diff --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c --- a/clang/test/Analysis/string.c +++ b/clang/test/Analysis/string.c @@ -363,6 +363,14 @@ strcpy(x, y); // no-warning } +void* func_strcpy_no_assertion(); +char*** ptr_strcpy_no_assertion; +void strcpy_no_assertion() { + *(unsigned char **)ptr_strcpy_no_assertion = (unsigned char*)(func_strcpy_no_assertion()); + char c; + strcpy(**ptr_strcpy_no_assertion, &c); // no-assertion +} + //===----------------------------------------------------------------------=== // stpcpy() //===----------------------------------------------------------------------===