Skip to content
This repository was archived by the owner on Jun 30, 2025. It is now read-only.

Commit 644f0e9

Browse files
committed
Fix null terminator in Demangle function.
If the demangled name is longer than out_size, the null terminator is missing from the output. This will cause a crash in the DemangleInplace() function (symbolize.cc) when calling strlen on the buffer.
1 parent 2075ae8 commit 644f0e9

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

src/demangle.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1350,7 +1350,13 @@ bool Demangle(const char* mangled, char* out, size_t out_size) {
13501350
return false;
13511351
}
13521352

1353-
std::copy_n(unmangled.get(), std::min(n, out_size), out);
1353+
if (out_size > 0) {
1354+
// n is the size of the allocated buffer, not the length of the string.
1355+
// Therefore, it includes the terminating zero (and possibly additional space).
1356+
std::size_t copy_size = std::min(n-1, out_size - 1);
1357+
std::copy_n(unmangled.get(), copy_size, out);
1358+
out[copy_size] = '\0'; // Ensure terminating null if n > out_size
1359+
}
13541360
return status == 0;
13551361
#else
13561362
State state;

src/symbolize_unittest.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
#include "symbolize.h"
3535

3636
#include <csignal>
37+
#include <cstring>
3738
#include <iostream>
39+
#include <map>
40+
#include <string>
41+
3842

3943
#include "config.h"
4044
#include "glog/logging.h"
@@ -133,6 +137,18 @@ TEST(Symbolize, Symbolize) {
133137

134138
struct Foo {
135139
static void func(int x);
140+
static size_t longParamFunc(
141+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p0,
142+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p1,
143+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p2,
144+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p3,
145+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p4,
146+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p5,
147+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p6,
148+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p7,
149+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p8,
150+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p9
151+
);
136152
};
137153

138154
void ATTRIBUTE_NOINLINE Foo::func(int x) {
@@ -142,6 +158,21 @@ void ATTRIBUTE_NOINLINE Foo::func(int x) {
142158
a = a + 1;
143159
}
144160

161+
size_t ATTRIBUTE_NOINLINE Foo::longParamFunc(
162+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p0,
163+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p1,
164+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p2,
165+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p3,
166+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p4,
167+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p5,
168+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p6,
169+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p7,
170+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p8,
171+
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p9
172+
) {
173+
return p0.size() + p1.size() + p2.size() + p3.size() + p4.size() + p5.size() + p6.size() + p7.size() + p8.size() + p9.size();
174+
}
175+
145176
// With a modern GCC, Symbolize() should return demangled symbol
146177
// names. Function parameters should be omitted.
147178
# ifdef TEST_WITH_MODERN_GCC
@@ -150,6 +181,10 @@ TEST(Symbolize, SymbolizeWithDemangling) {
150181
# if !defined(_MSC_VER) || !defined(NDEBUG)
151182
# if defined(HAVE___CXA_DEMANGLE)
152183
EXPECT_STREQ("Foo::func(int)", TrySymbolize((void*)(&Foo::func)));
184+
// Very long functions can be truncated, but we should not crash or return null.
185+
// Also the result should start properly.
186+
const char* symbol = TrySymbolize((void*)(&Foo::longParamFunc));
187+
EXPECT_TRUE(symbol == std::strstr(symbol, "Foo::longParamFunc("));
153188
# else
154189
EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func)));
155190
# endif

0 commit comments

Comments
 (0)