Skip to content

Commit 201c4b9

Browse files
committed
[demangler] Rust demangler buffer return
The rust demangler has some odd buffer handling code, which will copy the demangled string into the provided buffer, if it will fit. Otherwise it uses the allocated buffer it made. But the length of the incoming buffer will have come from a previous call, which was the length of the demangled string -- not the buffer size. And of course, we're unconditionally allocating a temporary buffer in the first place. So we don't actually get buffer reuse, and we get a memcpy in somecases. However, nothing in LLVM ever passes in a non-null pointer. Neither does anything pass in a status pointer that is then made use of. The only exercise these have is in the test suite. So let's just make the rust demangler have the same API as the dlang demangler. Reviewed By: tmiasko Differential Revision: https://reviews.llvm.org/D123420
1 parent ccaf6da commit 201c4b9

File tree

6 files changed

+13
-104
lines changed

6 files changed

+13
-104
lines changed

lldb/source/Core/Mangled.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ static char *GetItaniumDemangledStr(const char *M) {
168168
}
169169

170170
static char *GetRustV0DemangledStr(const char *M) {
171-
char *demangled_cstr = llvm::rustDemangle(M, nullptr, nullptr, nullptr);
171+
char *demangled_cstr = llvm::rustDemangle(M);
172172

173173
if (Log *log = GetLog(LLDBLog::Demangle)) {
174174
if (demangled_cstr && demangled_cstr[0])

llvm/include/llvm/Demangle/Demangle.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ char *microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf,
5757
size_t *n_buf, int *status,
5858
MSDemangleFlags Flags = MSDF_None);
5959

60-
// Demangles a Rust v0 mangled symbol. The API follows that of __cxa_demangle.
61-
char *rustDemangle(const char *MangledName, char *Buf, size_t *N, int *Status);
60+
// Demangles a Rust v0 mangled symbol.
61+
char *rustDemangle(const char *MangledName);
6262

6363
// Demangles a D mangled symbol.
6464
char *dlangDemangle(const char *MangledName);

llvm/lib/Demangle/Demangle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) {
5151
if (isItaniumEncoding(MangledName))
5252
Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr);
5353
else if (isRustEncoding(MangledName))
54-
Demangled = rustDemangle(MangledName, nullptr, nullptr, nullptr);
54+
Demangled = rustDemangle(MangledName);
5555
else if (isDLangEncoding(MangledName))
5656
Demangled = dlangDemangle(MangledName);
5757

llvm/lib/Demangle/RustDemangle.cpp

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -147,57 +147,27 @@ class Demangler {
147147

148148
} // namespace
149149

150-
char *llvm::rustDemangle(const char *MangledName, char *Buf, size_t *N,
151-
int *Status) {
152-
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
153-
if (Status != nullptr)
154-
*Status = demangle_invalid_args;
150+
char *llvm::rustDemangle(const char *MangledName) {
151+
if (MangledName == nullptr)
155152
return nullptr;
156-
}
157153

158154
// Return early if mangled name doesn't look like a Rust symbol.
159155
StringView Mangled(MangledName);
160-
if (!Mangled.startsWith("_R")) {
161-
if (Status != nullptr)
162-
*Status = demangle_invalid_mangled_name;
156+
if (!Mangled.startsWith("_R"))
163157
return nullptr;
164-
}
165158

166159
Demangler D;
167-
if (!initializeOutputBuffer(nullptr, nullptr, D.Output, 1024)) {
168-
if (Status != nullptr)
169-
*Status = demangle_memory_alloc_failure;
160+
if (!initializeOutputBuffer(nullptr, nullptr, D.Output, 1024))
170161
return nullptr;
171-
}
172162

173163
if (!D.demangle(Mangled)) {
174-
if (Status != nullptr)
175-
*Status = demangle_invalid_mangled_name;
176164
std::free(D.Output.getBuffer());
177165
return nullptr;
178166
}
179167

180168
D.Output += '\0';
181-
char *Demangled = D.Output.getBuffer();
182-
size_t DemangledLen = D.Output.getCurrentPosition();
183-
184-
if (Buf != nullptr) {
185-
if (DemangledLen <= *N) {
186-
std::memcpy(Buf, Demangled, DemangledLen);
187-
std::free(Demangled);
188-
Demangled = Buf;
189-
} else {
190-
std::free(Buf);
191-
}
192-
}
193-
194-
if (N != nullptr)
195-
*N = DemangledLen;
196-
197-
if (Status != nullptr)
198-
*Status = demangle_success;
199169

200-
return Demangled;
170+
return D.Output.getBuffer();
201171
}
202172

203173
Demangler::Demangler(size_t MaxRecursionLevel)

llvm/tools/llvm-rust-demangle-fuzzer/llvm-rust-demangle-fuzzer.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313

1414
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
1515
std::string NullTerminatedString((const char *)Data, Size);
16-
int Status = 0;
17-
char *Demangled = llvm::rustDemangle(NullTerminatedString.c_str(), nullptr,
18-
nullptr, &Status);
16+
char *Demangled = llvm::rustDemangle(NullTerminatedString.c_str());
1917
std::free(Demangled);
2018
return 0;
2119
}

llvm/unittests/Demangle/RustDemangleTest.cpp

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,78 +13,19 @@
1313
#include <cstdlib>
1414

1515
TEST(RustDemangle, Success) {
16-
char *Demangled =
17-
llvm::rustDemangle("_RNvC1a4main", nullptr, nullptr, nullptr);
18-
EXPECT_STREQ(Demangled, "a::main");
19-
std::free(Demangled);
20-
21-
// With status.
22-
int Status = 0;
23-
Demangled = llvm::rustDemangle("_RNvC1a4main", nullptr, nullptr, &Status);
24-
EXPECT_EQ(Status, llvm::demangle_success);
25-
EXPECT_STREQ(Demangled, "a::main");
26-
std::free(Demangled);
27-
28-
// With status and length.
29-
size_t N = 0;
30-
Demangled = llvm::rustDemangle("_RNvC1a4main", nullptr, &N, &Status);
31-
EXPECT_EQ(Status, llvm::demangle_success);
32-
EXPECT_EQ(N, 8u);
16+
char *Demangled = llvm::rustDemangle("_RNvC1a4main");
3317
EXPECT_STREQ(Demangled, "a::main");
3418
std::free(Demangled);
3519
}
3620

3721
TEST(RustDemangle, Invalid) {
38-
int Status = 0;
3922
char *Demangled = nullptr;
4023

4124
// Invalid prefix.
42-
Demangled = llvm::rustDemangle("_ABCDEF", nullptr, nullptr, &Status);
43-
EXPECT_EQ(Status, llvm::demangle_invalid_mangled_name);
25+
Demangled = llvm::rustDemangle("_ABCDEF");
4426
EXPECT_EQ(Demangled, nullptr);
4527

4628
// Correct prefix but still invalid.
47-
Demangled = llvm::rustDemangle("_RRR", nullptr, nullptr, &Status);
48-
EXPECT_EQ(Status, llvm::demangle_invalid_mangled_name);
29+
Demangled = llvm::rustDemangle("_RRR");
4930
EXPECT_EQ(Demangled, nullptr);
5031
}
51-
52-
TEST(RustDemangle, OutputBufferWithoutLength) {
53-
char *Buffer = static_cast<char *>(std::malloc(1024));
54-
ASSERT_NE(Buffer, nullptr);
55-
56-
int Status = 0;
57-
char *Demangled =
58-
llvm::rustDemangle("_RNvC1a4main", Buffer, nullptr, &Status);
59-
60-
EXPECT_EQ(Status, llvm::demangle_invalid_args);
61-
EXPECT_EQ(Demangled, nullptr);
62-
std::free(Buffer);
63-
}
64-
65-
TEST(RustDemangle, OutputBuffer) {
66-
size_t N = 1024;
67-
char *Buffer = static_cast<char *>(std::malloc(N));
68-
ASSERT_NE(Buffer, nullptr);
69-
70-
int Status = 0;
71-
char *Demangled = llvm::rustDemangle("_RNvC1a4main", Buffer, &N, &Status);
72-
73-
EXPECT_EQ(Status, llvm::demangle_success);
74-
EXPECT_EQ(Demangled, Buffer);
75-
EXPECT_STREQ(Demangled, "a::main");
76-
std::free(Demangled);
77-
}
78-
79-
TEST(RustDemangle, SmallOutputBuffer) {
80-
size_t N = 1;
81-
char *Buffer = static_cast<char *>(std::malloc(N));
82-
ASSERT_NE(Buffer, nullptr);
83-
84-
int Status = 0;
85-
char *Demangled = llvm::rustDemangle("_RNvC1a4main", Buffer, &N, &Status);
86-
87-
EXPECT_EQ(Status, llvm::demangle_success);
88-
EXPECT_STREQ(Demangled, "a::main");
89-
std::free(Demangled);
90-
}

0 commit comments

Comments
 (0)