mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-04-02 22:06:26 +00:00
Harden malformed vehicle packet parsing
This commit is contained in:
@@ -670,7 +670,13 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
Client->Disconnect("TCPRcv failed");
|
Client->Disconnect("TCPRcv failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this, false);
|
try {
|
||||||
|
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this, false);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
beammp_warnf("Failed to receive/parse packet via TCP from client {}: {}", Client->GetID(), e.what());
|
||||||
|
Client->Disconnect("Failed to parse packet");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QueueSync.joinable())
|
if (QueueSync.joinable())
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <any>
|
#include <any>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
@@ -54,6 +55,15 @@ static std::optional<std::pair<int, int>> GetPidVid(const std::string& str) {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::optional<std::string> ExtractStructuredPayload(const std::string& PacketData, char BeginMarker) {
|
||||||
|
auto FoundPos = PacketData.find(BeginMarker);
|
||||||
|
if (FoundPos == std::string::npos) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PacketData.substr(FoundPos);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("GetPidVid") {
|
TEST_CASE("GetPidVid") {
|
||||||
SUBCASE("Valid singledigit") {
|
SUBCASE("Valid singledigit") {
|
||||||
const auto MaybePidVid = GetPidVid("0-1");
|
const auto MaybePidVid = GetPidVid("0-1");
|
||||||
@@ -121,6 +131,13 @@ TEST_CASE("GetPidVid") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ExtractStructuredPayload") {
|
||||||
|
CHECK_EQ(ExtractStructuredPayload("1-2:{\"reset\":true}", '{').value(), "{\"reset\":true}");
|
||||||
|
CHECK_EQ(ExtractStructuredPayload("1-2:[0,1,2,3]", '[').value(), "[0,1,2,3]");
|
||||||
|
CHECK_FALSE(ExtractStructuredPayload("1-2:null", '{').has_value());
|
||||||
|
CHECK_FALSE(ExtractStructuredPayload("1-2:null", '[').has_value());
|
||||||
|
}
|
||||||
|
|
||||||
TServer::TServer(const std::vector<std::string_view>& Arguments) {
|
TServer::TServer(const std::vector<std::string_view>& Arguments) {
|
||||||
beammp_info("BeamMP Server v" + Application::ServerVersionString());
|
beammp_info("BeamMP Server v" + Application::ServerVersionString());
|
||||||
Application::SetSubsystemStatus("Server", Application::Status::Starting);
|
Application::SetSubsystemStatus("Server", Application::Status::Starting);
|
||||||
@@ -472,7 +489,13 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
Data = Data.substr(Data.find('{'));
|
auto ResetData = ExtractStructuredPayload(Data, '{');
|
||||||
|
if (!ResetData.has_value()) {
|
||||||
|
beammp_warnf("Malformed 'Or' packet from client {}: missing '{{' in '{}'", c.GetID(), Packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data = std::move(ResetData.value());
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", "", c.GetID(), VID, Data));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleReset", "", c.GetID(), VID, Data));
|
||||||
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
||||||
}
|
}
|
||||||
@@ -501,7 +524,13 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||||
Data = Data.substr(Data.find('['));
|
auto PaintData = ExtractStructuredPayload(Data, '[');
|
||||||
|
if (!PaintData.has_value()) {
|
||||||
|
beammp_warnf("Malformed 'Op' packet from client {}: missing '[' in '{}'", c.GetID(), Packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data = std::move(PaintData.value());
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehiclePaintChanged", "", c.GetID(), VID, Data));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehiclePaintChanged", "", c.GetID(), VID, Data));
|
||||||
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user