From d4457d139a715bab0b6a72ddf1bee5943eda7f5a Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Wed, 20 Apr 2022 10:53:12 -0400
Subject: [PATCH] Regex hardening

---
 indra/llcommon/llregex.h                     | 15 +++++++++++++++
 indra/llcommon/llsdserialize_xml.cpp         |  8 ++++----
 indra/llui/llurlentry.cpp                    |  2 +-
 indra/newview/llappviewer.cpp                |  2 +-
 indra/newview/llfloatertos.cpp               |  3 ++-
 indra/newview/llnotificationofferhandler.cpp |  7 +++----
 indra/newview/llviewermenu.cpp               |  7 +++----
 7 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/indra/llcommon/llregex.h b/indra/llcommon/llregex.h
index 2b7f5e47c2b..c29b1f44ee4 100644
--- a/indra/llcommon/llregex.h
+++ b/indra/llcommon/llregex.h
@@ -86,4 +86,19 @@ bool ll_regex_search(const S& string, const R& regex)
 		return false;
 	}
 }
+
+template <typename S, typename R, typename F>
+std::string ll_regex_replace(const S& string, const R& regex, const F& fmt)
+{
+	try
+	{
+		return boost::regex_replace(string, regex, fmt);
+	}
+	catch (const std::runtime_error& e)
+	{
+		LL_WARNS() << "error searching with '" << regex.str() << "': "
+			<< e.what() << ":\n'" << string << "'" << LL_ENDL;
+		return {};
+	}
+}
 #endif  // LLREGEX_H
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index c751288c4d6..a5681d084f7 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -31,7 +31,8 @@
 #include <deque>
 
 #include "apr_base64.h"
-#include <boost/regex.hpp>
+
+#include "llregex.h"
 
 extern "C"
 {
@@ -775,9 +776,8 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
 			// created by python and other non-linden systems - DEV-39358
 			// Fortunately we have very little binary passing now,
 			// so performance impact shold be negligible. + poppy 2009-09-04
-			boost::regex r;
-			r.assign("\\s");
-			std::string stripped = boost::regex_replace(mCurrentContent, r, "");
+			static const boost::regex binary_regex("\\s");
+			std::string stripped = ll_regex_replace(mCurrentContent, binary_regex, "");
 			S32 len = apr_base64_decode_len(stripped.c_str());
 			std::vector<U8> data;
 			data.resize(len);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 331a380fa45..1c00f34ac3b 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -1597,7 +1597,7 @@ std::string LLUrlEntryIPv6::getQuery(const std::string &url) const
 	boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase);
 	boost::match_results<std::string::const_iterator> matches;
 
-	return boost::regex_replace(url, regex, "");
+	return ll_regex_replace(url, regex, "");
 }
 
 std::string LLUrlEntryIPv6::getUrl(const std::string &string) const
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 86696065bed..b45797bac0a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3157,7 +3157,7 @@ LLSD LLAppViewer::getViewerInfo() const
 			info["REGION"] = gAgent.getRegion()->getName();
 
 			boost::regex regex("\\.(secondlife|lindenlab)\\..*");
-			info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, "");
+			info["HOSTNAME"] = ll_regex_replace(gAgent.getRegion()->getSimHostName(), regex, "");
 			info["SERVER_VERSION"] = gLastVersionChannel;
 			LLSLURL slurl;
 			LLAgentUI::buildSLURL(slurl);
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index 857f5adc344..e0cb842034c 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -45,6 +45,7 @@
 #include "llstartup.h"              // login_alert_done
 #include "llcorehttputil.h"
 #include "llfloaterreg.h"
+#include "llregex.h"
 
 // system includes
 #include <boost/regex.hpp>
@@ -93,7 +94,7 @@ BOOL LLFloaterTOS::postBuild()
 			boost::regex::perl | boost::regex::icase);
 
 		//IF it has http:// in it, we use the web browser
-		if(mMessage.size() >= 4 && boost::regex_match(mMessage, url_regex))
+		if(mMessage.size() >= 4 && ll_regex_match(mMessage, url_regex))
 		{
 			// it exists
 			use_web_browser = true;
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 2b58ac82503..16e6615166f 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -40,7 +40,7 @@
 #include "rlvactions.h"
 // [/RLVa:KB]
 
-#include <boost/regex.hpp>
+#include "llregex.h"
 
 using namespace LLNotificationsUI;
 
@@ -164,9 +164,8 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification,
 				|| notification->getName() == "TeleportOffered_MaturityExceeded"
 				|| notification->getName() == "TeleportOffered_MaturityBlocked"))
 			{
-				boost::regex r("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>( - )?",
-					boost::regex::perl|boost::regex::icase);
-				std::string stripped_msg = boost::regex_replace(notification->getMessage(), r, "");
+				static const boost::regex r("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>( - )?", boost::regex::perl|boost::regex::icase);
+				std::string stripped_msg = ll_regex_replace(notification->getMessage(), r, "");
 				LLHandlerUtil::logToIMP2P(notification->getPayload()["from_id"], stripped_msg,file_only);
 			}
 			else
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index e401c687423..0f5960d6d7e 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -99,6 +99,7 @@
 #include "llmenuoptionpathfindingrebakenavmesh.h"
 #include "llmoveview.h"
 #include "llparcel.h"
+#include "llregex.h"
 #include "llrootview.h"
 #include "llsceneview.h"
 #include "llscenemonitor.h"
@@ -135,7 +136,6 @@
 #include "llpathfindingmanager.h"
 #include "llstartup.h"
 #include "boost/unordered_map.hpp"
-#include <boost/regex.hpp>
 #include <boost/algorithm/string.hpp>
 #include "llcleanup.h"
 #include "llviewershadermgr.h"
@@ -8665,9 +8665,8 @@ void handle_report_bug(const LLSD& param)
 	
 	LLStringUtil::format_map_t replace;
 	std::string environment = LLAppViewer::instance()->getViewerInfoString(true);
-	boost::regex regex;
-	regex.assign("</?nolink>");
-	std::string stripped_env = boost::regex_replace(environment, regex, "");
+	const boost::regex regex("</?nolink>");
+	std::string stripped_env = ll_regex_replace(environment, regex, "");
 
 	replace["[ENVIRONMENT]"] = LLURI::escape(stripped_env);
 	LLSLURL location_url;
-- 
GitLab