From bce4721097d33b324db0331ed40bb2e5f45c4d14 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 21 Jan 2021 11:59:27 +0000
Subject: [PATCH] SL-14597 Fixed deprecated function and added signal handling
 Signal handling is ugly, but so far that's the only option that works

Approved-by: Maxim Nikolenko <maximnproductengine@lindenlab.com>
Approved-by: Andrey Lihatskiy <andreylproductengine@lindenlab.com>
---
 indra/llcommon/lluriparser.cpp | 78 +++++++++++++++++++++++-----------
 indra/llcommon/lluriparser.h   |  1 -
 2 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp
index 015ff2d7c30..e4f229dd163 100644
--- a/indra/llcommon/lluriparser.cpp
+++ b/indra/llcommon/lluriparser.cpp
@@ -29,10 +29,13 @@
 #include "linden_common.h"
 #include "lluriparser.h"
 
+#if LL_DARWIN
+#include <signal.h>
+#include <setjmp.h>
+#endif
+
 LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedTmp(false), mRes(0)
 {
-	mState.uri = &mUri;
-
 	if (u.find("://") == std::string::npos)
 	{
 		mNormalizedUri = "http://";
@@ -51,7 +54,7 @@ LLUriParser::~LLUriParser()
 
 S32 LLUriParser::parse()
 {
-	mRes = uriParseUriA(&mState, mNormalizedUri.c_str());
+	mRes = uriParseSingleUriA(&mUri, mNormalizedUri.c_str(), NULL);
 	return mRes;
 }
 
@@ -158,42 +161,69 @@ void LLUriParser::extractParts()
 	}
 }
 
+#if LL_DARWIN
+typedef void(*sighandler_t)(int);
+jmp_buf return_to_normalize;
+void uri_signal_handler(int signal)
+{
+    // Apparently signal handler throwing an exception doesn't work.
+    // This is ugly and unsafe due to not unwinding content of uriparser library,
+    // but unless we have a way to catch this as NSexception, jump appears to be the only option.
+    longjmp(return_to_normalize, 1 /*setjmp will return this value*/);
+}
+#endif
+
 S32 LLUriParser::normalize()
 {
 	mNormalizedTmp = mTmpScheme;
 	if (!mRes)
 	{
-        // Uriparser is 3p software we can not directly fix.
-        // On winodws this probably requires SEH handling, but all
-        // crashes so far were on MAC in scope of uriNormalizeSyntaxExA.
-        try
+#if LL_DARWIN
+        sighandler_t last_handler;
+        last_handler = signal(SIGILL, &uri_signal_handler);		// illegal instruction
+        if (setjmp(return_to_normalize))
+        {
+            // Issue: external library crashed via signal
+            // If you encountered this, please try to figure out what's wrong:
+            // 1. Verify that library's input is 'sane'
+            // 2. Check if we have an NSexception to work with (unlikely)
+            // 3. See if passing same string causes exception to repeat
+            //
+            // Crash happens at uriNormalizeSyntaxExA
+            // Warning!!! This does not properly unwind stack,
+            // if this can be handled by NSexception, it needs to be remade
+            llassert(0);
+
+            LL_WARNS() << "Uriparser crashed with SIGILL, while processing: " << mNormalizedUri << LL_ENDL;
+            signal(SIGILL, last_handler);
+            return 1;
+        }
+#endif
+
+        mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST);
+
+#if LL_DARWIN
+        signal(SIGILL, last_handler);
+#endif
+
+        if (!mRes)
         {
-            mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST);
+            S32 chars_required;
+            mRes = uriToStringCharsRequiredA(&mUri, &chars_required);
 
             if (!mRes)
             {
-                S32 chars_required;
-                mRes = uriToStringCharsRequiredA(&mUri, &chars_required);
+                chars_required++;
+                std::vector<char> label_buf(chars_required);
+                mRes = uriToStringA(&label_buf[0], &mUri, chars_required, NULL);
 
                 if (!mRes)
                 {
-                    chars_required++;
-                    std::vector<char> label_buf(chars_required);
-                    mRes = uriToStringA(&label_buf[0], &mUri, chars_required, NULL);
-
-                    if (!mRes)
-                    {
-                        mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0];
-                        mTmpScheme = false;
-                    }
+                    mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0];
+                    mTmpScheme = false;
                 }
             }
         }
-        catch (...)
-        {
-            // At this point mNormalizedUri should contain http+unmodified input string.
-            LL_WARNS() << "Uriparser crashed processing: " << mNormalizedUri << LL_ENDL;
-        }
 	}
 
 	if(mTmpScheme)
diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h
index cfbf54f3c85..92626b90540 100644
--- a/indra/llcommon/lluriparser.h
+++ b/indra/llcommon/lluriparser.h
@@ -76,7 +76,6 @@ class LL_COMMON_API LLUriParser
 	std::string mFragment;
 	std::string mNormalizedUri;
 
-	UriParserStateA mState;
 	UriUriA mUri;
 
 	S32 mRes;
-- 
GitLab