[clang] [analyzer] Fix assertion failed caused by non standard strnlen function (PR #150222)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 23 06:39:28 PDT 2025
https://github.com/flovent created https://github.com/llvm/llvm-project/pull/150222
Fix assertion failed and avoid further model non standard `strnlen` like this:
```
char* strnlen(const char*, size_t)
```
Fixes #149757.
>From cec3aa7177075962f1980fa8787debc79afe7fe9 Mon Sep 17 00:00:00 2001
From: flovent <flbven at protonmail.com>
Date: Wed, 23 Jul 2025 21:29:55 +0800
Subject: [PATCH] [analyzer] Fix assertion failed caused by non standard
strnlen function
---
.../Checkers/CStringChecker.cpp | 20 ++++++++++++-------
.../Analysis/cstring-no-standard-function.c | 14 +++++++++++++
2 files changed, 27 insertions(+), 7 deletions(-)
create mode 100644 clang/test/Analysis/cstring-no-standard-function.c
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<NonLoc>();
+ std::optional<NonLoc> resultNL = result.getAs<NonLoc>();
+ if (!resultNL)
+ return;
if (strLengthNL) {
- state = state->assume(C.getSValBuilder().evalBinOpNN(
- state, BO_LE, resultNL, *strLengthNL, cmpTy)
- .castAs<DefinedOrUnknownSVal>(), true);
+ state = state->assume(
+ C.getSValBuilder()
+ .evalBinOpNN(state, BO_LE, *resultNL, *strLengthNL, cmpTy)
+ .castAs<DefinedOrUnknownSVal>(),
+ true);
}
if (maxlenValNL) {
- state = state->assume(C.getSValBuilder().evalBinOpNN(
- state, BO_LE, resultNL, *maxlenValNL, cmpTy)
- .castAs<DefinedOrUnknownSVal>(), true);
+ state = state->assume(
+ C.getSValBuilder()
+ .evalBinOpNN(state, BO_LE, *resultNL, *maxlenValNL, cmpTy)
+ .castAs<DefinedOrUnknownSVal>(),
+ 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
+}
More information about the cfe-commits
mailing list