Skip to content

Commit

Permalink
Fix null terminator in Demangle function.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
martonka committed Oct 28, 2024
1 parent 2075ae8 commit 530d7a7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/demangle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,9 @@ bool Demangle(const char* mangled, char* out, size_t out_size) {
}

std::copy_n(unmangled.get(), std::min(n, out_size), out);
if(n > out_size) {
out[out_size-1] = '\0';
}
return status == 0;
#else
State state;
Expand Down
34 changes: 34 additions & 0 deletions src/symbolize_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@

#include <csignal>
#include <iostream>
#include <map>
#include <string>


#include "config.h"
#include "glog/logging.h"
Expand Down Expand Up @@ -133,6 +136,18 @@ TEST(Symbolize, Symbolize) {

struct Foo {
static void func(int x);
static void longParamFunc(
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p0,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p1,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p2,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p3,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p4,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p5,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p6,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p7,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p8,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p9
);
};

void ATTRIBUTE_NOINLINE Foo::func(int x) {
Expand All @@ -142,6 +157,22 @@ void ATTRIBUTE_NOINLINE Foo::func(int x) {
a = a + 1;
}

void ATTRIBUTE_NOINLINE Foo::longParamFunc(
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p0,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p1,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p2,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p3,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p4,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p5,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p6,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p7,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p8,
std::map<std::map<std::string, std::string>,std::map<std::string, std::string> > p9
) {
volatile int a = p0.size() + p1.size() + p2.size() + p3.size() + p4.size() + p5.size() + p6.size() + p7.size() + p8.size() + p9.size();
a = a + 1;
}

// With a modern GCC, Symbolize() should return demangled symbol
// names. Function parameters should be omitted.
# ifdef TEST_WITH_MODERN_GCC
Expand All @@ -150,6 +181,9 @@ TEST(Symbolize, SymbolizeWithDemangling) {
# if !defined(_MSC_VER) || !defined(NDEBUG)
# if defined(HAVE___CXA_DEMANGLE)
EXPECT_STREQ("Foo::func(int)", TrySymbolize((void*)(&Foo::func)));
// Very long functions can be truncated, but we should not crash or return null
// Also the result should start properly.
EXPECT_TRUE(0 == std::string( TrySymbolize( (void*)(&Foo::longParamFunc))).find("Foo::longParamFunc("));
# else
EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func)));
# endif
Expand Down

0 comments on commit 530d7a7

Please sign in to comment.