Give microsoftDemangle() an outparam for how many input bytes were consumed.
authorNico Weber <thakis@chromium.org>
Mon, 18 May 2020 23:57:30 +0000 (19:57 -0400)
committerNico Weber <thakis@chromium.org>
Wed, 20 May 2020 20:17:31 +0000 (16:17 -0400)
Demangling Itanium symbols either consumes the whole input or fails,
but Microsoft symbols can be successfully demangled with just some
of the input.

Add an outparam that enables clients to know how much of the input was
consumed, and use this flag to give llvm-undname an opt-in warning
on partially consumed symbols.

Differential Revision: https://reviews.llvm.org/D80173

lldb/source/Core/Mangled.cpp
llvm/include/llvm/Demangle/Demangle.h
llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
llvm/lib/Demangle/Demangle.cpp
llvm/lib/Demangle/MicrosoftDemangle.cpp
llvm/test/Demangle/warn-trailing.test [new file with mode: 0644]
llvm/tools/llvm-microsoft-demangle-fuzzer/llvm-microsoft-demangle-fuzzer.cpp
llvm/tools/llvm-objdump/COFFDump.cpp
llvm/tools/llvm-undname/llvm-undname.cpp

index b44cbeb..56914ae 100644 (file)
@@ -181,7 +181,7 @@ void Mangled::SetValue(ConstString name) {
 // Local helpers for different demangling implementations.
 static char *GetMSVCDemangledStr(const char *M) {
   char *demangled_cstr = llvm::microsoftDemangle(
-      M, nullptr, nullptr, nullptr,
+      M, nullptr, nullptr, nullptr, nullptr,
       llvm::MSDemangleFlags(llvm::MSDF_NoAccessSpecifier |
                             llvm::MSDF_NoCallingConvention |
                             llvm::MSDF_NoMemberType));
index 7b85b9a..b4006a0 100644 (file)
@@ -40,7 +40,21 @@ enum MSDemangleFlags {
   MSDF_NoReturnType = 1 << 3,
   MSDF_NoMemberType = 1 << 4,
 };
-char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
+
+/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
+/// Returns a pointer to the start of a null-terminated demangled string on
+/// success, or nullptr on error.
+/// If n_read is non-null and demangling was successful, it receives how many
+/// bytes of the input string were consumed.
+/// buf can point to a *n_buf bytes large buffer where the demangled name is
+/// stored. If the buffer is too small, it is grown with realloc(). If buf is
+/// nullptr, then this malloc()s memory for the result.
+/// *n_buf stores the size of buf on input if buf is non-nullptr, and it
+/// receives the size of the demangled string on output if n_buf is not nullptr.
+/// status receives one of the demangle_ enum entries above if it's not nullptr.
+/// Flags controls various details of the demangled representation.
+char *microsoftDemangle(const char *mangled_name, size_t *n_read,
+                        char *buf, size_t *n_buf,
                         int *status, MSDemangleFlags Flags = MSDF_None);
 
 /// Attempt to demangle a string using different demangling schemes.
index ff017b0..b055230 100644 (file)
@@ -624,7 +624,7 @@ LLVMSymbolizer::DemangleName(const std::string &Name,
     // Only do MSVC C++ demangling on symbols starting with '?'.
     int status = 0;
     char *DemangledName = microsoftDemangle(
-        Name.c_str(), nullptr, nullptr, &status,
+        Name.c_str(), nullptr, nullptr, nullptr, &status,
         MSDemangleFlags(MSDF_NoAccessSpecifier | MSDF_NoCallingConvention |
                         MSDF_NoMemberType | MSDF_NoReturnType));
     if (status != 0)
index 5f92153..71dafa0 100644 (file)
@@ -24,8 +24,8 @@ std::string llvm::demangle(const std::string &MangledName) {
   if (isItaniumEncoding(MangledName))
     Demangled = itaniumDemangle(MangledName.c_str(), nullptr, nullptr, nullptr);
   else
-    Demangled =
-        microsoftDemangle(MangledName.c_str(), nullptr, nullptr, nullptr);
+    Demangled = microsoftDemangle(MangledName.c_str(), nullptr, nullptr,
+                                  nullptr, nullptr);
 
   if (!Demangled)
     return MangledName;
index c681d6e..1607431 100644 (file)
@@ -2334,14 +2334,16 @@ void Demangler::dumpBackReferences() {
     std::printf("\n");
 }
 
-char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N,
+char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled,
+                              char *Buf, size_t *N,
                               int *Status, MSDemangleFlags Flags) {
-  int InternalStatus = demangle_success;
   Demangler D;
   OutputStream S;
 
   StringView Name{MangledName};
   SymbolNode *AST = D.parse(Name);
+  if (!D.Error && NMangled)
+    *NMangled = Name.begin() - MangledName;
 
   if (Flags & MSDF_DumpBackrefs)
     D.dumpBackReferences();
@@ -2356,6 +2358,7 @@ char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N,
   if (Flags & MSDF_NoMemberType)
     OF = OutputFlags(OF | OF_NoMemberType);
 
+  int InternalStatus = demangle_success;
   if (D.Error)
     InternalStatus = demangle_invalid_mangled_name;
   else if (!initializeOutputStream(Buf, N, S, 1024))
diff --git a/llvm/test/Demangle/warn-trailing.test b/llvm/test/Demangle/warn-trailing.test
new file mode 100644 (file)
index 0000000..6219e44
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: llvm-undname -warn-trailing 2>&1 < %s | FileCheck %s
+
+?x@@3HAasdf
+; CHECK: ?x@@3HAasdf
+; CHECK-NEXT: int x
+; CHECK-NEXT: warning: trailing characters: asdf
index 2aa4d8d..64dd483 100644 (file)
@@ -15,6 +15,6 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   std::string NullTerminatedString((const char *)Data, Size);
   free(llvm::microsoftDemangle(NullTerminatedString.c_str(), nullptr, nullptr,
-                               nullptr));
+                               nullptr, nullptr));
   return 0;
 }
index 1e817d8..c829b49 100644 (file)
@@ -679,11 +679,9 @@ void objdump::printCOFFSymbolTable(const COFFObjectFile *coff) {
            << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
            << Name;
     if (Demangle && Name.startswith("?")) {
-      char *DemangledSymbol = nullptr;
-      size_t Size = 0;
       int Status = -1;
-      DemangledSymbol =
-          microsoftDemangle(Name.data(), DemangledSymbol, &Size, &Status);
+      char *DemangledSymbol =
+          microsoftDemangle(Name.data(), nullptr, nullptr, nullptr, &Status);
 
       if (Status == 0 && DemangledSymbol) {
         outs() << " (" << StringRef(DemangledSymbol) << ")";
index 7c36825..f9f9e05 100644 (file)
@@ -45,6 +45,9 @@ cl::opt<bool> NoMemberType("no-member-type", cl::Optional,
                            cl::init(false));
 cl::opt<std::string> RawFile("raw-file", cl::Optional,
                              cl::desc("for fuzzer data"), cl::Hidden);
+cl::opt<bool> WarnTrailing("warn-trailing", cl::Optional,
+                           cl::desc("warn on trailing characters"), cl::Hidden,
+                           cl::init(false));
 cl::list<std::string> Symbols(cl::Positional, cl::desc("<input symbols>"),
                               cl::ZeroOrMore);
 
@@ -62,11 +65,15 @@ static bool msDemangle(const std::string &S) {
   if (NoMemberType)
     Flags = MSDemangleFlags(Flags | MSDF_NoMemberType);
 
+  size_t NRead;
   char *ResultBuf =
-      microsoftDemangle(S.c_str(), nullptr, nullptr, &Status, Flags);
+      microsoftDemangle(S.c_str(), &NRead, nullptr, nullptr, &Status, Flags);
   if (Status == llvm::demangle_success) {
     outs() << ResultBuf << "\n";
     outs().flush();
+    if (WarnTrailing && NRead < S.size())
+      WithColor::warning() << "trailing characters: " << S.c_str() + NRead
+                           << "\n";
   } else {
     WithColor::error() << "Invalid mangled name\n";
   }