summaryrefslogtreecommitdiff
path: root/indra/llcommon/llerror.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2019-12-12 07:39:23 -0500
committerNat Goodspeed <nat@lindenlab.com>2020-03-25 15:28:17 -0400
commit1fc7c994d6232e373fc9f36e72ed9855d4d7cd76 (patch)
tree641cd3e26083b67f3d993acf74cde3a10cd100fb /indra/llcommon/llerror.cpp
parent6586918df0039f60c1c02c134a6a0e0762997d56 (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/llcommon/llerror.cpp')
-rw-r--r--indra/llcommon/llerror.cpp37
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
}