diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2019-12-12 07:39:23 -0500 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2020-03-25 15:28:17 -0400 |
commit | 1fc7c994d6232e373fc9f36e72ed9855d4d7cd76 (patch) | |
tree | 641cd3e26083b67f3d993acf74cde3a10cd100fb /indra | |
parent | 6586918df0039f60c1c02c134a6a0e0762997d56 (diff) |
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.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llcommon/llerror.cpp | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 335a0995fe..83d380fafd 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -302,28 +302,35 @@ namespace LLError { #ifdef __GNUC__ // GCC: type_info::name() returns a mangled class name,st demangle - // passing nullptr, 0 forces allocation of a unique buffer we can free - // fixing MAINT-8724 on OSX 10.14 + // passing nullptr, 0 forces allocation of a unique buffer we can free + // fixing MAINT-8724 on OSX 10.14 int status = -1; char* name = abi::__cxa_demangle(mangled, nullptr, 0, &status); - std::string result(name ? name : mangled); - free(name); - return result; -#elif LL_WINDOWS - // DevStudio: type_info::name() includes the text "class " at the start + std::string result(name ? name : mangled); + free(name); + return result; - 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; - 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 '" - << name << "'" << LL_ENDL; - return name; + // in Python, " or ".join(vector) -- but in C++, a PITB + LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '" + << name << "'" << LL_ENDL; } + return name; - return name.substr(class_prefix.length()); - -#else +#else // neither GCC nor Visual Studio return mangled; #endif } |