From 48e708e498bf57dacf1d943008c7074b900e75b3 Mon Sep 17 00:00:00 2001
From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com>
Date: Sun, 28 Aug 2022 17:12:58 +0200
Subject: [PATCH] CPylon: Exception handling for all 'json::parse' calls

---
 r5dev/engine/cmodel_bsp.cpp     |   6 +-
 r5dev/engine/server/sv_main.cpp |   2 +-
 r5dev/networksystem/pylon.cpp   | 322 +++++++++++++++++---------------
 r5dev/networksystem/pylon.h     |   2 +-
 4 files changed, 179 insertions(+), 153 deletions(-)

diff --git a/r5dev/engine/cmodel_bsp.cpp b/r5dev/engine/cmodel_bsp.cpp
index 4a1a99bd..6607cfe9 100644
--- a/r5dev/engine/cmodel_bsp.cpp
+++ b/r5dev/engine/cmodel_bsp.cpp
@@ -49,9 +49,8 @@ void MOD_GetAllInstalledMaps()
         if (!smRegexMatches.empty())
         {
             if (smRegexMatches[1].str().compare("frontend") == 0)
-            {
                 continue;
-            }
+
             else if (smRegexMatches[1].str().compare("mp_common") == 0)
             {
                 if (std::find(g_vAllMaps.begin(), g_vAllMaps.end(), "mp_lobby") == g_vAllMaps.end())
@@ -349,10 +348,9 @@ void MOD_PreloadPakFile(const string& svLevelName)
     FileSystem()->Read(pBuf, nLen, pFile);
     FileSystem()->Close(pFile);
 
-    nlohmann::json jsIn;
     try
     {
-        jsIn = nlohmann::json::parse(pBuf);
+        nlohmann::json jsIn = nlohmann::json::parse(pBuf);
         if (!jsIn.is_null())
         {
             if (!jsIn["rpak"].is_null())
diff --git a/r5dev/engine/server/sv_main.cpp b/r5dev/engine/server/sv_main.cpp
index d241535d..f3c4ad54 100644
--- a/r5dev/engine/server/sv_main.cpp
+++ b/r5dev/engine/server/sv_main.cpp
@@ -12,7 +12,7 @@ void SV_IsClientBanned(CPylon* pPylon, const string& svIPAddr, const uint64_t nN
 {
 	string svError;
 
-	bool bCompBanned = pPylon->GetClientIsBanned(svIPAddr, nNucleusID, svError);
+	bool bCompBanned = pPylon->CheckForBan(svIPAddr, nNucleusID, svError);
 	if (bCompBanned)
 	{
 		DevMsg(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from the master server!)\n", svIPAddr.c_str(), nNucleusID);
diff --git a/r5dev/networksystem/pylon.cpp b/r5dev/networksystem/pylon.cpp
index c3d73e06..48ad946f 100644
--- a/r5dev/networksystem/pylon.cpp
+++ b/r5dev/networksystem/pylon.cpp
@@ -51,76 +51,83 @@ vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
 
     if (htResult && pylon_showdebug->GetBool())
     {
-        DevMsg(eDLL_T::ENGINE, "%s - replied with '%d'.\n", __FUNCTION__, htResult->status);
+        DevMsg(eDLL_T::ENGINE, "%s - Replied with '%d'.\n", __FUNCTION__, htResult->status);
     }
 
-    if (htResult && htResult->status == 200) // STATUS_OK
+    try
     {
-        nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
-        if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
+        if (htResult && htResult->status == 200) // STATUS_OK
         {
-            for (auto& obj : jsResultBody["servers"])
+            nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
+            if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
             {
-                vslList.push_back(
-                    NetGameServer_t
-                    {
-                        obj.value("name",""),
-                        obj.value("description",""),
-                        obj.value("hidden","false") == "true",
-                        obj.value("map",""),
-                        obj.value("playlist",""),
-                        obj.value("ip",""),
-                        obj.value("port", ""),
-                        obj.value("key",""),
-                        obj.value("checksum",""),
-                        obj.value("version", SDK_VERSION),
-                        obj.value("playerCount", ""),
-                        obj.value("maxPlayers", ""),
-                        obj.value("timeStamp", 0),
-                        obj.value("publicRef", ""),
-                        obj.value("cachedID", ""),
-                    }
-                );
-            }
-        }
-        else
-        {
-            if (jsResultBody["err"].is_string())
-            {
-                svOutMessage = jsResultBody["err"].get<string>();
+                for (auto& obj : jsResultBody["servers"])
+                {
+                    vslList.push_back(
+                        NetGameServer_t
+                        {
+                            obj.value("name",""),
+                            obj.value("description",""),
+                            obj.value("hidden","false") == "true",
+                            obj.value("map",""),
+                            obj.value("playlist",""),
+                            obj.value("ip",""),
+                            obj.value("port", ""),
+                            obj.value("key",""),
+                            obj.value("checksum",""),
+                            obj.value("version", SDK_VERSION),
+                            obj.value("playerCount", ""),
+                            obj.value("maxPlayers", ""),
+                            obj.value("timeStamp", 0),
+                            obj.value("publicRef", ""),
+                            obj.value("cachedID", ""),
+                        }
+                    );
+                }
             }
             else
             {
-                svOutMessage = "An unknown error occured!";
-            }
-        }
-    }
-    else
-    {
-        if (htResult)
-        {
-            if (!htResult->body.empty())
-            {
-                nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
-
                 if (jsResultBody["err"].is_string())
                 {
                     svOutMessage = jsResultBody["err"].get<string>();
                 }
                 else
                 {
-                    svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+                    svOutMessage = "An unknown error occured!";
+                }
+            }
+        }
+        else
+        {
+            if (htResult)
+            {
+                if (!htResult->body.empty())
+                {
+                    nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
+
+                    if (jsResultBody["err"].is_string())
+                    {
+                        svOutMessage = jsResultBody["err"].get<string>();
+                    }
+                    else
+                    {
+                        svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+                    }
+
+                    return vslList;
                 }
 
+                svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
                 return vslList;
             }
 
-            svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+            svOutMessage = "Failed to reach comp-server: Unknown error code";
             return vslList;
         }
-
-        svOutMessage = "Failed to reach comp-server: Unknown error code";
-        return vslList;
+    }
+    catch (const std::exception& ex)
+    {
+        Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
     }
 
     return vslList;
@@ -166,64 +173,71 @@ bool CPylon::PostServerHost(string& svOutMessage, string& svOutToken, const NetG
         DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with '%d'\n", __FUNCTION__, htResult->status);
     }
 
-    if (htResult && htResult->status == 200) // STATUS_OK
+    try
     {
-        nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
-        if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
+        if (htResult && htResult->status == 200) // STATUS_OK
         {
-            if (jsResultBody["token"].is_string())
+            nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
+            if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
             {
-                svOutToken = jsResultBody["token"].get<string>();
+                if (jsResultBody["token"].is_string())
+                {
+                    svOutToken = jsResultBody["token"].get<string>();
+                }
+                else
+                {
+                    svOutToken = string();
+                }
+
+                return true;
             }
             else
             {
-                svOutToken = string();
-            }
-
-            return true;
-        }
-        else
-        {
-            if (jsResultBody["err"].is_string())
-            {
-                svOutMessage = jsResultBody["err"].get<string>();
-            }
-            else
-            {
-                svOutMessage = "An unknown error occured!";
-            }
-            return false;
-        }
-    }
-    else
-    {
-        if (htResult)
-        {
-            if (!htResult->body.empty())
-            {
-                nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
-
                 if (jsResultBody["err"].is_string())
                 {
                     svOutMessage = jsResultBody["err"].get<string>();
                 }
                 else
                 {
-                    svOutMessage = string("Failed to reach comp-server ") + std::to_string(htResult->status);
+                    svOutMessage = "An unknown error occured!";
+                }
+                return false;
+            }
+        }
+        else
+        {
+            if (htResult)
+            {
+                if (!htResult->body.empty())
+                {
+                    nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
+
+                    if (jsResultBody["err"].is_string())
+                    {
+                        svOutMessage = jsResultBody["err"].get<string>();
+                    }
+                    else
+                    {
+                        svOutMessage = string("Failed to reach comp-server ") + std::to_string(htResult->status);
+                    }
+
+                    svOutToken = string();
+                    return false;
                 }
 
                 svOutToken = string();
+                svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
                 return false;
             }
 
             svOutToken = string();
-            svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+            svOutMessage = "Failed to reach comp-server: Unknown error code";
             return false;
         }
-
-        svOutToken = string();
-        svOutMessage = "Failed to reach comp-server: Unknown error code";
-        return false;
+    }
+    catch (const std::exception& ex)
+    {
+        Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
     }
 
     return false;
@@ -256,77 +270,84 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
         DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with '%d'\n", __FUNCTION__, htResult->status);
     }
 
-    if (htResult && htResult->status == 200) // STATUS_OK
+    try
     {
-        if (!htResult->body.empty())
-        {
-            nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
-
-            if (htResult && jsResultBody["success"].is_boolean() && jsResultBody["success"])
-            {
-                slOutServer = NetGameServer_t
-                {
-                        jsResultBody["server"].value("name",""),
-                        jsResultBody["server"].value("description",""),
-                        jsResultBody["server"].value("hidden","false") == "true",
-                        jsResultBody["server"].value("map",""),
-                        jsResultBody["server"].value("playlist",""),
-                        jsResultBody["server"].value("ip",""),
-                        jsResultBody["server"].value("port", ""),
-                        jsResultBody["server"].value("key",""),
-                        jsResultBody["server"].value("checksum",""),
-                        jsResultBody["server"].value("version", SDK_VERSION),
-                        jsResultBody["server"].value("playerCount", ""),
-                        jsResultBody["server"].value("maxPlayers", ""),
-                        jsResultBody["server"].value("timeStamp", 0),
-                        jsResultBody["server"].value("publicRef", ""),
-                        jsResultBody["server"].value("cachedID", ""),
-                };
-                return true;
-            }
-            else
-            {
-                if (jsResultBody["err"].is_string())
-                {
-                    svOutMessage = jsResultBody["err"].get<string>();
-                }
-                else
-                {
-                    svOutMessage = "";
-                }
-
-                slOutServer = NetGameServer_t{};
-                return false;
-            }
-        }
-    }
-    else
-    {
-        if (htResult)
+        if (htResult && htResult->status == 200) // STATUS_OK
         {
             if (!htResult->body.empty())
             {
                 nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
 
-                if (jsResultBody["err"].is_string())
+                if (htResult && jsResultBody["success"].is_boolean() && jsResultBody["success"])
                 {
-                    svOutMessage = jsResultBody["err"].get<string>();
+                    slOutServer = NetGameServer_t
+                    {
+                            jsResultBody["server"].value("name",""),
+                            jsResultBody["server"].value("description",""),
+                            jsResultBody["server"].value("hidden","false") == "true",
+                            jsResultBody["server"].value("map",""),
+                            jsResultBody["server"].value("playlist",""),
+                            jsResultBody["server"].value("ip",""),
+                            jsResultBody["server"].value("port", ""),
+                            jsResultBody["server"].value("key",""),
+                            jsResultBody["server"].value("checksum",""),
+                            jsResultBody["server"].value("version", SDK_VERSION),
+                            jsResultBody["server"].value("playerCount", ""),
+                            jsResultBody["server"].value("maxPlayers", ""),
+                            jsResultBody["server"].value("timeStamp", 0),
+                            jsResultBody["server"].value("publicRef", ""),
+                            jsResultBody["server"].value("cachedID", ""),
+                    };
+                    return true;
                 }
                 else
                 {
-                    svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+                    if (jsResultBody["err"].is_string())
+                    {
+                        svOutMessage = jsResultBody["err"].get<string>();
+                    }
+                    else
+                    {
+                        svOutMessage = "";
+                    }
+
+                    slOutServer = NetGameServer_t{};
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            if (htResult)
+            {
+                if (!htResult->body.empty())
+                {
+                    nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
+
+                    if (jsResultBody["err"].is_string())
+                    {
+                        svOutMessage = jsResultBody["err"].get<string>();
+                    }
+                    else
+                    {
+                        svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+                    }
+
+                    return false;
                 }
 
+                svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
                 return false;
             }
 
-            svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
+            svOutMessage = "Failed to reach comp-server: Unknown error code";
+            slOutServer = NetGameServer_t{};
             return false;
         }
-
-        svOutMessage = "Failed to reach comp-server: Unknown error code";
-        slOutServer = NetGameServer_t{};
-        return false;
+    }
+    catch (const std::exception& ex)
+    {
+        Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
     }
 
     return false;
@@ -339,7 +360,7 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
 //			&svOutErrCl - 
 // Output : Returns true if banned, false if not banned.
 //-----------------------------------------------------------------------------
-bool CPylon::GetClientIsBanned(const string& svIpAddress, uint64_t nOriginID, string& svOutErrCl)
+bool CPylon::CheckForBan(const string& svIpAddress, uint64_t nOriginID, string& svOutErrCl)
 {
     nlohmann::json jsRequestBody = nlohmann::json::object();
     jsRequestBody["oid"] = nOriginID;
@@ -348,18 +369,25 @@ bool CPylon::GetClientIsBanned(const string& svIpAddress, uint64_t nOriginID, st
     httplib::Client htClient(pylon_matchmaking_hostname->GetString()); htClient.set_connection_timeout(10);
     httplib::Result htResult = htClient.Post("/banlist/isBanned", jsRequestBody.dump(4).c_str(), jsRequestBody.dump(4).length(), "application/json");
 
-    if (htResult && htResult->status == 200)
+    try
     {
-        nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
-        if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
+        if (htResult && htResult->status == 200)
         {
-            if (jsResultBody["banned"].is_boolean() && jsResultBody["banned"].get<bool>())
+            nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
+            if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
             {
-                svOutErrCl = jsResultBody.value("errCl", "#DISCONNECT_BANNED");
-                return true;
+                if (jsResultBody["banned"].is_boolean() && jsResultBody["banned"].get<bool>())
+                {
+                    svOutErrCl = jsResultBody.value("errCl", "#DISCONNECT_BANNED");
+                    return true;
+                }
             }
         }
     }
+    catch (const std::exception& ex)
+    {
+        Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
+    }
     return false;
 }
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/r5dev/networksystem/pylon.h b/r5dev/networksystem/pylon.h
index 36e28d5d..c93086bc 100644
--- a/r5dev/networksystem/pylon.h
+++ b/r5dev/networksystem/pylon.h
@@ -9,6 +9,6 @@ public:
 	vector<NetGameServer_t> GetServerList(string& svOutMessage);
 	bool PostServerHost(string& svOutMessage, string& svOutToken, const NetGameServer_t& slServerListing);
 	bool GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage, const string& svToken);
-	bool GetClientIsBanned(const string& svIpAddress, uint64_t nOriginID, string& svOutErrCl);
+	bool CheckForBan(const string& svIpAddress, uint64_t nOriginID, string& svOutErrCl);
 };
 extern CPylon* g_pMasterServer;