SymbolizedFrame::name is already null-terminated
authorTudor Bosman <tudorb@fb.com>
Sun, 20 Apr 2014 15:02:08 +0000 (08:02 -0700)
committerDave Watson <davejwatson@fb.com>
Tue, 20 May 2014 19:53:56 +0000 (12:53 -0700)
Summary:
... as it comes from Elf::getSymbolName, which returns null-terminated C
strings. So there's no need to copy it into a fixed-size buffer (and have a
buffer overflow, ouch).

Test Plan: folly/experimental/symbolizer_test, see what else "arc unit" gets us

Reviewed By: tconerly@fb.com

FB internal diff: D1286348

folly/experimental/symbolizer/Symbolizer.cpp
folly/experimental/symbolizer/Symbolizer.h
folly/experimental/symbolizer/test/SymbolizerTest.cpp

index ac30db8c7013ad382199804b78212eee6eee5629..38c925a3e8bb7b9866f40fa85351cb76bdbc003a 100644 (file)
@@ -172,10 +172,7 @@ void SymbolizedFrame::set(const std::shared_ptr<ElfFile>& file,
   }
 
   file_ = file;
-  auto name = file->getSymbolName(sym);
-  if (name) {
-    this->name = name;
-  }
+  name = file->getSymbolName(sym);
 
   Dwarf(file.get()).findAddress(address, location);
 }
@@ -306,25 +303,18 @@ void SymbolizePrinter::print(uintptr_t address, const SymbolizedFrame& frame) {
                          sizeof(padBuf) - 1 - (16 - 2 * sizeof(uintptr_t)));
 
   color(kFunctionColor);
-  char mangledBuf[1024];
   if (!frame.found) {
     doPrint(" (not found)");
     return;
   }
 
-  if (frame.name.empty()) {
+  if (!frame.name || frame.name[0] == '\0') {
     doPrint(" (unknown)");
-  } else if (frame.name.size() >= sizeof(mangledBuf)) {
-    doPrint(" ");
-    doPrint(frame.name);
   } else {
-    memcpy(mangledBuf, frame.name.data(), frame.name.size());
-    mangledBuf[frame.name.size()] = '\0';
-
     char demangledBuf[1024];
-    demangle(mangledBuf, demangledBuf, sizeof(demangledBuf));
+    demangle(frame.name, demangledBuf, sizeof(demangledBuf));
     doPrint(" ");
-    doPrint(demangledBuf);
+    doPrint(demangledBuf[0] == '\0' ? frame.name : demangledBuf);
   }
 
   if (!(options_ & NO_FILE_AND_LINE)) {
@@ -392,14 +382,10 @@ void SymbolizePrinter::println(uintptr_t address,
 
 void SymbolizePrinter::printTerse(uintptr_t address,
                                   const SymbolizedFrame& frame) {
-  if (frame.found) {
-    char mangledBuf[1024];
-    memcpy(mangledBuf, frame.name.data(), frame.name.size());
-    mangledBuf[frame.name.size()] = '\0';
-
+  if (frame.found && frame.name && frame.name[0] != '\0') {
     char demangledBuf[1024] = {0};
-    demangle(mangledBuf, demangledBuf, sizeof(demangledBuf));
-    doPrint(strlen(demangledBuf) == 0 ? "(unknown)" : demangledBuf);
+    demangle(frame.name, demangledBuf, sizeof(demangledBuf));
+    doPrint(demangledBuf[0] == '\0' ? frame.name : demangledBuf);
   } else {
     // Can't use sprintf, not async-signal-safe
     static_assert(sizeof(uintptr_t) <= 8, "huge uintptr_t?");
index 0000614114431f85c8ad87d53a03ee473efa2b95..88619a99d032ba8d8a6a61c412e7bc28c1a6f886 100644 (file)
@@ -38,21 +38,21 @@ class Symbolizer;
  * Frame information: symbol name and location.
  */
 struct SymbolizedFrame {
-  SymbolizedFrame() : found(false) { }
+  SymbolizedFrame() : found(false), name(nullptr) { }
 
   void set(const std::shared_ptr<ElfFile>& file, uintptr_t address);
   void clear() { *this = SymbolizedFrame(); }
 
   bool isSignalFrame;
   bool found;
-  StringPiece name;
+  const char* name;
   Dwarf::LocationInfo location;
 
   /**
    * Demangle the name and return it. Not async-signal-safe; allocates memory.
    */
   fbstring demangledName() const {
-    return demangle(name.fbstr().c_str());
+    return name ? demangle(name) : fbstring();
   }
  private:
   std::shared_ptr<ElfFile> file_;
index d283dc823f171224219949ef50ebdaa54f746be1..73862553cb7ebec7483bcde06649226b87face13 100644 (file)
@@ -32,8 +32,7 @@ TEST(Symbolizer, Single) {
   Symbolizer symbolizer;
   SymbolizedFrame a;
   ASSERT_TRUE(symbolizer.symbolize(reinterpret_cast<uintptr_t>(foo), a));
-  EXPECT_EQ("folly::symbolizer::test::foo()",
-            demangle(a.name.str().c_str()));
+  EXPECT_EQ("folly::symbolizer::test::foo()", a.demangledName());
 
   auto path = a.location.file.toString();
   folly::StringPiece basename(path);
@@ -80,14 +79,12 @@ void ElfCacheTest::SetUp() {
 void runElfCacheTest(Symbolizer& symbolizer) {
   FrameArray<100> frames = goldenFrames;
   for (size_t i = 0; i < frames.frameCount; ++i) {
-    auto& f = frames.frames[i];
-    f.found = false;
-    f.name.clear();
+    frames.frames[i].clear();
   }
   symbolizer.symbolize(frames);
   ASSERT_LE(4, frames.frameCount);
   for (size_t i = 1; i < 4; ++i) {
-    EXPECT_EQ(goldenFrames.frames[i].name, frames.frames[i].name);
+    EXPECT_STREQ(goldenFrames.frames[i].name, frames.frames[i].name);
   }
 }