[llvm] [Demangle] Prevent Node::Kind from being overwritten by copy/move assignment (PR #181588)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 15 17:15:10 PST 2026
https://github.com/ChouUn updated https://github.com/llvm/llvm-project/pull/181588
>From 17110b3d8389209a94035ccece58bb9f65162d31 Mon Sep 17 00:00:00 2001
From: ChouUn <ChouUnSoft at gmail.com>
Date: Mon, 16 Feb 2026 08:37:49 +0800
Subject: [PATCH] [Demangle] Prevent Node::Kind from being overwritten by
copy/move assignment
In Demangler::demangleFunctionEncoding, a ThunkSignatureNode is
populated by slice-copying a FunctionSignatureNode into it. The
default copy assignment operator copies all base class fields
including the private Node::Kind, which changes the node's kind
from ThunkSignature to FunctionSignature.
Fix this by defining custom copy/move assignment operators for Node
that preserve Kind. This field represents the node's dynamic type
and should never be overwritten by assignment.
Co-Authored-By: Claude Opus 4.6 <noreply at anthropic.com>
---
.../llvm/Demangle/MicrosoftDemangleNodes.h | 5 +++
llvm/lib/Demangle/MicrosoftDemangle.cpp | 3 ++
llvm/unittests/Demangle/CMakeLists.txt | 1 +
.../Demangle/MicrosoftDemangleTest.cpp | 37 +++++++++++++++++++
4 files changed, 46 insertions(+)
create mode 100644 llvm/unittests/Demangle/MicrosoftDemangleTest.cpp
diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
index 711aa70a4a8d3..d6187ff3b58e0 100644
--- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
+++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
@@ -278,6 +278,11 @@ struct Node {
explicit Node(NodeKind K) : Kind(K) {}
virtual ~Node() = default;
+ // Kind represents the node's dynamic type and must not be overwritten by
+ // copy/move assignment (e.g. when slicing a derived node into a base).
+ Node &operator=(const Node &) { return *this; }
+ Node &operator=(Node &&) { return *this; }
+
NodeKind kind() const { return Kind; }
virtual void output(OutputBuffer &OB, OutputFlags Flags) const = 0;
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 769dbd4f2eb6e..e70b8ad5abbf2 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -1983,6 +1983,9 @@ Demangler::demangleFunctionEncoding(std::string_view &MangledName) {
return nullptr;
if (TTN) {
+ // Copy the FunctionSignatureNode fields into the ThunkSignatureNode.
+ // Node::operator= intentionally does not copy Kind, so TTN retains its
+ // ThunkSignature kind through this slice assignment.
*static_cast<FunctionSignatureNode *>(TTN) = *FSN;
FSN = TTN;
}
diff --git a/llvm/unittests/Demangle/CMakeLists.txt b/llvm/unittests/Demangle/CMakeLists.txt
index 105af816e2ca0..02153d2d63a50 100644
--- a/llvm/unittests/Demangle/CMakeLists.txt
+++ b/llvm/unittests/Demangle/CMakeLists.txt
@@ -7,6 +7,7 @@ add_llvm_unittest(DemangleTests
DemangleTest.cpp
DLangDemangleTest.cpp
ItaniumDemangleTest.cpp
+ MicrosoftDemangleTest.cpp
OutputBufferTest.cpp
PartialDemangleTest.cpp
RustDemangleTest.cpp
diff --git a/llvm/unittests/Demangle/MicrosoftDemangleTest.cpp b/llvm/unittests/Demangle/MicrosoftDemangleTest.cpp
new file mode 100644
index 0000000000000..0beababaea441
--- /dev/null
+++ b/llvm/unittests/Demangle/MicrosoftDemangleTest.cpp
@@ -0,0 +1,37 @@
+//===-- MicrosoftDemangleTest.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Demangle/MicrosoftDemangle.h"
+#include "llvm/Demangle/MicrosoftDemangleNodes.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::ms_demangle;
+
+// After demangling a thunk function, the Signature node should retain
+// NodeKind::ThunkSignature. A base-class slice assignment in
+// demangleFunctionEncoding() currently overwrites the Kind field,
+// causing it to become NodeKind::FunctionSignature instead.
+TEST(MicrosoftDemangle, ThunkSignaturePreservesNodeKind) {
+ // ?f at C@@WBA at EAAHXZ demangles to:
+ // [thunk]: public: virtual int __cdecl C::f`adjustor{16}'(void)
+ // 'W' = FC_Public | FC_Virtual | FC_StaticThisAdjust
+ Demangler D;
+ std::string_view MangledName = "?f at C@@WBA at EAAHXZ";
+ SymbolNode *S = D.parse(MangledName);
+ ASSERT_FALSE(D.Error);
+ ASSERT_NE(S, nullptr);
+ ASSERT_EQ(S->kind(), NodeKind::FunctionSymbol);
+
+ auto *FSN = static_cast<FunctionSymbolNode *>(S);
+ ASSERT_NE(FSN->Signature, nullptr);
+
+ // This is the key assertion: the signature must identify as a
+ // ThunkSignature, not a plain FunctionSignature.
+ EXPECT_EQ(FSN->Signature->kind(), NodeKind::ThunkSignature);
+}
More information about the llvm-commits
mailing list