diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 31cb150892a5d..738640029cfb0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -1767,18 +1767,24 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, // All we know is the return value is the min of the string length // and the limit. This is better than nothing. result = C.getSValBuilder().conjureSymbolVal(Call, C.blockCount()); - NonLoc resultNL = result.castAs(); + std::optional resultNL = result.getAs(); + if (!resultNL) + return; if (strLengthNL) { - state = state->assume(C.getSValBuilder().evalBinOpNN( - state, BO_LE, resultNL, *strLengthNL, cmpTy) - .castAs(), true); + state = state->assume( + C.getSValBuilder() + .evalBinOpNN(state, BO_LE, *resultNL, *strLengthNL, cmpTy) + .castAs(), + true); } if (maxlenValNL) { - state = state->assume(C.getSValBuilder().evalBinOpNN( - state, BO_LE, resultNL, *maxlenValNL, cmpTy) - .castAs(), true); + state = state->assume( + C.getSValBuilder() + .evalBinOpNN(state, BO_LE, *resultNL, *maxlenValNL, cmpTy) + .castAs(), + true); } } diff --git a/clang/test/Analysis/cstring-no-standard-function.c b/clang/test/Analysis/cstring-no-standard-function.c new file mode 100644 index 0000000000000..0ddb2c7696726 --- /dev/null +++ b/clang/test/Analysis/cstring-no-standard-function.c @@ -0,0 +1,14 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring -verify %s + +// expected-no-diagnostics + +typedef __SIZE_TYPE__ size_t; + +extern char* strnlen(const char*, size_t); +char** q; + +void f(const char *s) +{ + extern char a[8]; + q[0] = strnlen(a, 7); // no crash +}