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  	}  | 
