https://github.com/NagyDonat updated https://github.com/llvm/llvm-project/pull/229119
From bbd87b232ddb55e30e7c3fc7ae993c5482f38e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Mon, 5 Oct 2026 17:19:02 +0200 Subject: [PATCH 1/4] [analyzer] Ignore nonstandard function named 'memset' Previously CStringChecker ran into an assertion failure when it encountered a function named 'memset' whose third argument was a `const int &` instead of the standard `size_t`. This PR introduces an early return to avoid this. Fixes #228865 Reported-by: k-arrows --- .../StaticAnalyzer/Checkers/CStringChecker.cpp | 5 +++++ clang/test/Analysis/PR228865.cpp | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 clang/test/Analysis/PR228865.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 69712d15d50c4..1fce634e3c1c4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -2938,6 +2938,11 @@ void CStringChecker::evalMemset(CheckerContext &C, SVal SizeVal = C.getSVal(Size.Expression); QualType SizeTy = Size.Expression->getType(); + // Avoid assertion failure in the corner case when we see a function named + // 'memset' with a nonstandard declaration. + if (!SizeTy->isUnsignedIntegerType()) + return; + ProgramStateRef ZeroSize, NonZeroSize; std::tie(ZeroSize, NonZeroSize) = assumeZero(C, State, SizeVal, SizeTy); diff --git a/clang/test/Analysis/PR228865.cpp b/clang/test/Analysis/PR228865.cpp new file mode 100644 index 0000000000000..8951d7d0169b9 --- /dev/null +++ b/clang/test/Analysis/PR228865.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring -verify %s + +// Test that a nonstandard 'memset' does not trigger an assertion failure. +// Code taken from https://github.com/llvm/llvm-project/issues/228865 + +// expected-no-diagnostics + +struct B { +} b; + +struct A { + struct B b; +} a; + +void *memset(void *s, int c, const int &cond); + +void foo() { memset(&a.b, 0, sizeof(b)); } From 09937f58992dbf951efd2ce93d7e50aca5bab7f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Mon, 5 Oct 2026 21:32:13 +0200 Subject: [PATCH 2/4] Add comments in the test file --- clang/test/Analysis/PR228865.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/test/Analysis/PR228865.cpp b/clang/test/Analysis/PR228865.cpp index 8951d7d0169b9..648140ec7ea1c 100644 --- a/clang/test/Analysis/PR228865.cpp +++ b/clang/test/Analysis/PR228865.cpp @@ -12,6 +12,9 @@ struct A { struct B b; } a; +// Not the standard 'memset' -- there third parameter would be a 'size_t'. void *memset(void *s, int c, const int &cond); -void foo() { memset(&a.b, 0, sizeof(b)); } +void foo() { + memset(&a.b, 0, sizeof(b)); // no-crash +} From d5de72ed1b0f21b43d13807465bd8b9700b2631b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Mon, 5 Oct 2026 21:34:00 +0200 Subject: [PATCH 3/4] Fix typo --- clang/test/Analysis/PR228865.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Analysis/PR228865.cpp b/clang/test/Analysis/PR228865.cpp index 648140ec7ea1c..80569e7cfa106 100644 --- a/clang/test/Analysis/PR228865.cpp +++ b/clang/test/Analysis/PR228865.cpp @@ -12,7 +12,7 @@ struct A { struct B b; } a; -// Not the standard 'memset' -- there third parameter would be a 'size_t'. +// Not the standard 'memset' -- there the third parameter would be a 'size_t'. void *memset(void *s, int c, const int &cond); void foo() { From 535eff24f7393be2e5546928f8e3905abab7a4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Mon, 5 Oct 2026 22:47:16 +0200 Subject: [PATCH 4/4] Properly rule out reference types --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 2 +- clang/test/Analysis/PR228865.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 1fce634e3c1c4..3749c262e8bba 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -2940,7 +2940,7 @@ void CStringChecker::evalMemset(CheckerContext &C, // Avoid assertion failure in the corner case when we see a function named // 'memset' with a nonstandard declaration. - if (!SizeTy->isUnsignedIntegerType()) + if (!SizeTy->isUnsignedIntegerType() || !Size.Expression->isPRValue()) return; ProgramStateRef ZeroSize, NonZeroSize; diff --git a/clang/test/Analysis/PR228865.cpp b/clang/test/Analysis/PR228865.cpp index 80569e7cfa106..74c8e4a73da77 100644 --- a/clang/test/Analysis/PR228865.cpp +++ b/clang/test/Analysis/PR228865.cpp @@ -1,7 +1,7 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring -verify %s // Test that a nonstandard 'memset' does not trigger an assertion failure. -// Code taken from https://github.com/llvm/llvm-project/issues/228865 +// Code adapted from https://github.com/llvm/llvm-project/issues/228865 // expected-no-diagnostics @@ -13,7 +13,7 @@ struct A { } a; // Not the standard 'memset' -- there the third parameter would be a 'size_t'. -void *memset(void *s, int c, const int &cond); +void *memset(void *s, int c, const unsigned &cond); void foo() { memset(&a.b, 0, sizeof(b)); // no-crash _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
