Skip to content
Snippets Groups Projects
Commit 1fc7c994 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

DRTVWR-494: Fix VS LLError::Log::demangle() vulnerability.

The Windows implementation of demangle() assumed that a "mangled" class name
produced by typeid(class).name() always starts with the prefix "class ",
checked for that and removed it. If the mangled name didn't start with that
prefix, it would emit a debug message and return the full name.

When the class in question is actually a struct, the prefix is "struct "
instead. But when demangle() was being called before logging had been fully
initialized, the debug message remarking that it didn't start with "class "
crashed.

Look for either "class " or "struct " prefix. Remove whichever is found and
return the rest of the name. If neither is found, only log if logging is
available.
parent 6586918d
No related branches found
No related tags found
No related merge requests found
...@@ -302,28 +302,35 @@ namespace LLError ...@@ -302,28 +302,35 @@ namespace LLError
{ {
#ifdef __GNUC__ #ifdef __GNUC__
// GCC: type_info::name() returns a mangled class name,st demangle // GCC: type_info::name() returns a mangled class name,st demangle
// passing nullptr, 0 forces allocation of a unique buffer we can free // passing nullptr, 0 forces allocation of a unique buffer we can free
// fixing MAINT-8724 on OSX 10.14 // fixing MAINT-8724 on OSX 10.14
int status = -1; int status = -1;
char* name = abi::__cxa_demangle(mangled, nullptr, 0, &status); char* name = abi::__cxa_demangle(mangled, nullptr, 0, &status);
std::string result(name ? name : mangled); std::string result(name ? name : mangled);
free(name); free(name);
return result; return result;
#elif LL_WINDOWS
// DevStudio: type_info::name() includes the text "class " at the start
static const std::string class_prefix = "class "; #elif LL_WINDOWS
// Visual Studio: type_info::name() includes the text "class " at the start
std::string name = mangled; std::string name = mangled;
if (0 != name.compare(0, class_prefix.length(), class_prefix)) for (const auto& prefix : std::vector<std::string>{ "class ", "struct " })
{
if (0 == name.compare(0, prefix.length(), prefix))
{
return name.substr(prefix.length());
}
}
// huh, that's odd, we should see one or the other prefix -- but don't
// try to log unless logging is already initialized
if (is_available())
{ {
LL_DEBUGS() << "Did not see '" << class_prefix << "' prefix on '" // in Python, " or ".join(vector) -- but in C++, a PITB
<< name << "'" << LL_ENDL; LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '"
return name; << name << "'" << LL_ENDL;
} }
return name;
return name.substr(class_prefix.length()); #else // neither GCC nor Visual Studio
#else
return mangled; return mangled;
#endif #endif
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment