diff --git a/src/demangle.cc b/src/demangle.cc index 9902c1e10..d71e1c631 100644 --- a/src/demangle.cc +++ b/src/demangle.cc @@ -1350,7 +1350,9 @@ bool Demangle(const char* mangled, char* out, size_t out_size) { return false; } - std::copy_n(unmangled.get(), std::min(n, out_size), out); + size_t copy_size = std::min(n, out_size); + std::copy_n(unmangled.get(), copy_size, out); + out[copy_size - 1] = '\0'; // Ensure terminating null if n > out_size return status == 0; #else State state; diff --git a/src/symbolize_unittest.cc b/src/symbolize_unittest.cc index f07484e63..d0e3c05a4 100644 --- a/src/symbolize_unittest.cc +++ b/src/symbolize_unittest.cc @@ -34,7 +34,11 @@ #include "symbolize.h" #include +#include #include +#include +#include + #include "config.h" #include "glog/logging.h" @@ -133,6 +137,18 @@ TEST(Symbolize, Symbolize) { struct Foo { static void func(int x); + static size_t longParamFunc( + std::map,std::map > p0, + std::map,std::map > p1, + std::map,std::map > p2, + std::map,std::map > p3, + std::map,std::map > p4, + std::map,std::map > p5, + std::map,std::map > p6, + std::map,std::map > p7, + std::map,std::map > p8, + std::map,std::map > p9 + ); }; void ATTRIBUTE_NOINLINE Foo::func(int x) { @@ -142,6 +158,21 @@ void ATTRIBUTE_NOINLINE Foo::func(int x) { a = a + 1; } +size_t ATTRIBUTE_NOINLINE Foo::longParamFunc( + std::map,std::map > p0, + std::map,std::map > p1, + std::map,std::map > p2, + std::map,std::map > p3, + std::map,std::map > p4, + std::map,std::map > p5, + std::map,std::map > p6, + std::map,std::map > p7, + std::map,std::map > p8, + std::map,std::map > p9 + ) { + return p0.size() + p1.size() + p2.size() + p3.size() + p4.size() + p5.size() + p6.size() + p7.size() + p8.size() + p9.size(); +} + // With a modern GCC, Symbolize() should return demangled symbol // names. Function parameters should be omitted. # ifdef TEST_WITH_MODERN_GCC @@ -150,6 +181,10 @@ 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. + const char* symbol = TrySymbolize((void*)(&Foo::longParamFunc)); + EXPECT_TRUE(symbol == std::strstr(symbol, "Foo::longParamFunc(")); # else EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func))); # endif