[Demangle] convert itaniumDemangle and nonMicrosoftDemangle to use std::string_view

D149104 converted llvm::demangle to use std::string_view. Enabling
"expensive checks" (via -DLLVM_ENABLE_EXPENSIVE_CHECKS=ON) causes
lld/test/wasm/why-extract.s to fail. The reason for this is obscure:

Reason #10007 why std::string_view is dangerous:
Consider the following pattern:

  std::string_view s = ...;
  const char *c = s.data();
  std::strlen(c);

Is c a NUL-terminated C style string? It depends; but if it's not then
it's not safe to call std::strlen on the std::string_view::data().
std::string_view::length() should be used instead.

Fixing this fixes the one lone test that caught this.

microsoftDemangle, rustDemangle, and dlangDemangle should get this same
treatment, too. I will do that next.

Reviewed By: MaskRay, efriedma

Differential Revision: https://reviews.llvm.org/D149675
This commit is contained in:
Nick Desaulniers 2023-06-02 14:53:46 -07:00
parent fa98bdbd95
commit 61e1c3d80d
7 changed files with 25 additions and 21 deletions

View File

@ -31,7 +31,7 @@ enum : int {
/// Returns a non-NULL pointer to a NUL-terminated C style string
/// that should be explicitly freed, if successful. Otherwise, may return
/// nullptr if mangled_name is not a valid mangling or is nullptr.
char *itaniumDemangle(const char *mangled_name);
char *itaniumDemangle(std::string_view mangled_name);
enum MSDemangleFlags {
MSDF_None = 0,
@ -66,7 +66,7 @@ char *dlangDemangle(const char *MangledName);
/// demangling occurred.
std::string demangle(const std::string &MangledName);
bool nonMicrosoftDemangle(const char *MangledName, std::string &Result);
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
/// "Partial" demangler. This supports demangling a string into an AST
/// (typically an intermediate stage in itaniumDemangle) and querying certain

View File

@ -679,7 +679,7 @@ std::string
LLVMSymbolizer::DemangleName(const std::string &Name,
const SymbolizableModule *DbiModuleDescriptor) {
std::string Result;
if (nonMicrosoftDemangle(Name.c_str(), Result))
if (nonMicrosoftDemangle(Name, Result))
return Result;
if (!Name.empty() && Name.front() == '?') {
@ -700,7 +700,7 @@ LLVMSymbolizer::DemangleName(const std::string &Name,
std::string DemangledCName(demanglePE32ExternCFunc(Name));
// On i386 Windows, the C name mangling for different calling conventions
// may also be applied on top of the Itanium or Rust name mangling.
if (nonMicrosoftDemangle(DemangledCName.c_str(), Result))
if (nonMicrosoftDemangle(DemangledCName, Result))
return Result;
return DemangledCName;
}

View File

@ -30,10 +30,10 @@ std::string llvm::demangle(const std::string &MangledName) {
std::string Result;
const char *S = MangledName.c_str();
if (nonMicrosoftDemangle(S, Result))
if (nonMicrosoftDemangle(MangledName, Result))
return Result;
if (S[0] == '_' && nonMicrosoftDemangle(S + 1, Result))
if (S[0] == '_' && nonMicrosoftDemangle(MangledName.substr(1), Result))
return Result;
if (char *Demangled = microsoftDemangle(S, nullptr, nullptr)) {
@ -45,14 +45,15 @@ std::string llvm::demangle(const std::string &MangledName) {
return MangledName;
}
bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) {
bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
std::string &Result) {
char *Demangled = nullptr;
if (isItaniumEncoding(MangledName))
if (isItaniumEncoding(MangledName.data()))
Demangled = itaniumDemangle(MangledName);
else if (isRustEncoding(MangledName))
Demangled = rustDemangle(MangledName);
else if (isDLangEncoding(MangledName))
Demangled = dlangDemangle(MangledName);
else if (isRustEncoding(MangledName.data()))
Demangled = rustDemangle(MangledName.data());
else if (isDLangEncoding(MangledName.data()))
Demangled = dlangDemangle(MangledName.data());
if (!Demangled)
return false;

View File

@ -365,11 +365,12 @@ public:
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
char *llvm::itaniumDemangle(const char *MangledName) {
if (!MangledName)
char *llvm::itaniumDemangle(std::string_view MangledName) {
if (MangledName.empty())
return nullptr;
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
Demangler Parser(MangledName.data(),
MangledName.data() + MangledName.length());
Node *AST = Parser.parse();
if (!AST)
return nullptr;

View File

@ -8,6 +8,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/StringViewExtras.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
@ -71,10 +72,11 @@ static void error(const Twine &Message) {
}
static std::string demangle(const std::string &Mangled) {
const char *DecoratedStr = Mangled.c_str();
using llvm::itanium_demangle::starts_with;
std::string_view DecoratedStr = Mangled;
if (StripUnderscore)
if (DecoratedStr[0] == '_')
++DecoratedStr;
DecoratedStr.remove_prefix(1);
std::string Result;
if (nonMicrosoftDemangle(DecoratedStr, Result))
@ -86,9 +88,9 @@ static std::string demangle(const std::string &Mangled) {
if (Types)
Undecorated = itaniumDemangle(DecoratedStr);
if (!Undecorated && strncmp(DecoratedStr, "__imp_", 6) == 0) {
if (!Undecorated && starts_with(DecoratedStr, "__imp_")) {
Prefix = "import thunk for ";
Undecorated = itaniumDemangle(DecoratedStr + 6);
Undecorated = itaniumDemangle(DecoratedStr.substr(6));
}
Result = Undecorated ? Prefix + Undecorated : Mangled;

View File

@ -639,7 +639,7 @@ static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
static std::optional<std::string> demangle(StringRef Name) {
std::string Demangled;
if (nonMicrosoftDemangle(Name.str().c_str(), Demangled))
if (nonMicrosoftDemangle(Name, Demangled))
return Demangled;
return std::nullopt;
}

View File

@ -338,7 +338,7 @@ static bool writeReport(LocationInfoTy &LocationInfo) {
bool Printed = false;
if (!NoDemangle) {
if (char *Demangled = itaniumDemangle(FuncName.c_str())) {
if (char *Demangled = itaniumDemangle(FuncName)) {
OS << Demangled;
Printed = true;
std::free(Demangled);