https://github.com/steakhal created 
https://github.com/llvm/llvm-project/pull/179445

Requested the backport in 
https://github.com/llvm/llvm-project/pull/178923#issuecomment-3837025990

From aa8a8025ee6e09203b8ef57874360f74212f71f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20Benics?= <[email protected]>
Date: Mon, 2 Feb 2026 18:19:56 +0000
Subject: [PATCH 1/2] [analyzer] Fix crash when copying uninitialized data in
 function named "swap" (#178923)

So the RegionStore has some assumptions, namely that the
core.unitialized.Assign checker is enabled and detects copying Undefined
(read of uninitialized data) before the Store is instructed to model
this.

As it turns out, there is a little hack in the
UndefinedAssignmentChecker:
```c++
void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
                                           const Stmt *StoreE, bool AtDeclInit,
                                           CheckerContext &C) const {
  if (!val.isUndef())
    return;

  // Do not report assignments of uninitialized values inside swap functions.
  // This should allow to swap partially uninitialized structs
  if (const FunctionDecl *EnclosingFunctionDecl =
      dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
    if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
      return;
  // ...
```

This meant that no Sink node was inserted by the checker, thus the Store
would just go and try to fulfill the bind operation.

However, the Store also assumed that it's not going to see Undefined
vals, so that case wasn't handled, but simply cast the value to a
nonloc::CompoundVal.

The checker should have created the Sink node regardless if it wants to
emit a report or not.
In addition to this, I'm also hardedning the Store to also be able to
handle UndefinedVals a bit better.

The crash bisects to #118096, but that's only surfaced this issue.

Fixes #178797

(cherry picked from commit 5fbf4117e3ccacfd57805650a08739e88091b608)
---
 clang/lib/StaticAnalyzer/Core/RegionStore.cpp |  5 +----
 clang/test/Analysis/uninit-vals.cpp           | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp 
b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 4f4824a3616ce..3bb6247e20612 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2659,12 +2659,9 @@ 
RegionStoreManager::bindArray(LimitedRegionBindingsConstRef B,
     return bindAggregate(B, R, Init);
   }
 
-  if (isa<nonloc::SymbolVal>(Init))
+  if (isa<nonloc::SymbolVal, UnknownVal, UndefinedVal>(Init))
     return bindAggregate(B, R, Init);
 
-  if (Init.isUnknown())
-    return bindAggregate(B, R, UnknownVal());
-
   // Remaining case: explicit compound values.
   const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
diff --git a/clang/test/Analysis/uninit-vals.cpp 
b/clang/test/Analysis/uninit-vals.cpp
index 6ba56f0c4e78b..7775e6a2125d3 100644
--- a/clang/test/Analysis/uninit-vals.cpp
+++ b/clang/test/Analysis/uninit-vals.cpp
@@ -33,3 +33,21 @@ void foo() {
 }
 }
 
+namespace gh_178797 {
+struct SpecialBuffer {
+    SpecialBuffer() : src(defaultBuffer), dst(defaultBuffer) {}
+    int* src;
+    int* dst;
+    int defaultBuffer[2];
+};
+// Not really a swap, but we need an assignment assigning UndefinedVal
+// within a "swap" function to trigger this behavior.
+void swap(int& lhs, int& rhs) {
+    lhs = rhs; // no-crash
+    // Not reporting copying uninitialized data because that is explicitly 
suppressed in the checker.
+}
+void entry_point() {
+    SpecialBuffer special;
+    swap(*special.dst, *++special.src);
+}
+}  // namespace gh_178797

From 6bc8f3f67b0bdd3ba8bee993d7765120a7c27e20 Mon Sep 17 00:00:00 2001
From: Balazs Benics <[email protected]>
Date: Tue, 3 Feb 2026 13:05:17 +0100
Subject: [PATCH 2/2] Mention the fix in the clang ReleaseNotes

---
 clang/docs/ReleaseNotes.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a01339cfb7b57..edefb001cc3b1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -903,6 +903,8 @@ Crash and bug fixes
 - The ``core.builtin.BuiltinFunctions`` checker crashed when passing
   ``_BitInt(N)`` or ``__int128_t`` to ``__builtin_add_overflow`` or similar
   checked arithmetic builtin functions. (#GH173795)
+- Fixed a crash introduced in clang-20 when analyzing some "swap" functions.
+  (#GH178797)
 
 Improvements
 ^^^^^^^^^^^^

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to