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.
This commit is contained in:
parent
2075ae813b
commit
644f0e98ec
@ -1350,7 +1350,13 @@ bool Demangle(const char* mangled, char* out, size_t out_size) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::copy_n(unmangled.get(), std::min(n, out_size), out);
|
if (out_size > 0) {
|
||||||
|
// n is the size of the allocated buffer, not the length of the string.
|
||||||
|
// Therefore, it includes the terminating zero (and possibly additional space).
|
||||||
|
std::size_t copy_size = std::min(n-1, out_size - 1);
|
||||||
|
std::copy_n(unmangled.get(), copy_size, out);
|
||||||
|
out[copy_size] = '\0'; // Ensure terminating null if n > out_size
|
||||||
|
}
|
||||||
return status == 0;
|
return status == 0;
|
||||||
#else
|
#else
|
||||||
State state;
|
State state;
|
||||||
|
|||||||
@ -34,7 +34,11 @@
|
|||||||
#include "symbolize.h"
|
#include "symbolize.h"
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "glog/logging.h"
|
#include "glog/logging.h"
|
||||||
@ -133,6 +137,18 @@ TEST(Symbolize, Symbolize) {
|
|||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
static void func(int x);
|
static void func(int x);
|
||||||
|
static size_t 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) {
|
void ATTRIBUTE_NOINLINE Foo::func(int x) {
|
||||||
@ -142,6 +158,21 @@ void ATTRIBUTE_NOINLINE Foo::func(int x) {
|
|||||||
a = a + 1;
|
a = a + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t 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
|
||||||
|
) {
|
||||||
|
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
|
// With a modern GCC, Symbolize() should return demangled symbol
|
||||||
// names. Function parameters should be omitted.
|
// names. Function parameters should be omitted.
|
||||||
# ifdef TEST_WITH_MODERN_GCC
|
# ifdef TEST_WITH_MODERN_GCC
|
||||||
@ -150,6 +181,10 @@ TEST(Symbolize, SymbolizeWithDemangling) {
|
|||||||
# if !defined(_MSC_VER) || !defined(NDEBUG)
|
# if !defined(_MSC_VER) || !defined(NDEBUG)
|
||||||
# if defined(HAVE___CXA_DEMANGLE)
|
# if defined(HAVE___CXA_DEMANGLE)
|
||||||
EXPECT_STREQ("Foo::func(int)", TrySymbolize((void*)(&Foo::func)));
|
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
|
# else
|
||||||
EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func)));
|
EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func)));
|
||||||
# endif
|
# endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user