Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix exception propagation on packet decompression #365

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion include/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class Application final {
static inline std::mutex mShutdownHandlersMutex {};
static inline std::deque<TShutdownHandler> mShutdownHandlers {};

static inline Version mVersion { 3, 5, 0 };
static inline Version mVersion { 3, 5, 1 };
};

void SplitString(std::string const& str, const char delim, std::vector<std::string>& out);
Expand Down Expand Up @@ -268,3 +268,9 @@ std::vector<uint8_t> DeComp(std::span<const uint8_t> input);

std::string GetPlatformAgnosticErrorString();
#define S_DSN SU_RAW

class InvalidDataError : std::runtime_error {
public:
InvalidDataError() : std::runtime_error("Invalid data") {
}
};
6 changes: 5 additions & 1 deletion src/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,11 @@ std::vector<uint8_t> DeComp(std::span<const uint8_t> input) {
output_size = output_buffer.size();
} else if (res != Z_OK) {
beammp_error("zlib uncompress() failed: " + std::to_string(res));
throw std::runtime_error("zlib uncompress() failed");
if (res == Z_DATA_ERROR) {
throw InvalidDataError {};
} else {
throw std::runtime_error("zlib uncompress() failed");
}
} else if (res == Z_OK) {
break;
}
Expand Down
12 changes: 11 additions & 1 deletion src/TNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,17 @@ std::vector<uint8_t> TNetwork::TCPRcv(TClient& c) {
constexpr std::string_view ABG = "ABG:";
if (Data.size() >= ABG.size() && std::equal(Data.begin(), Data.begin() + ABG.size(), ABG.begin(), ABG.end())) {
Data.erase(Data.begin(), Data.begin() + ABG.size());
return DeComp(Data);
try {
return DeComp(Data);
} catch (const InvalidDataError& ) {
beammp_errorf("Failed to decompress packet from a client. The receive failed and the client may be disconnected as a result");
// return empty -> error
return std::vector<uint8_t>();
} catch (const std::runtime_error& e) {
beammp_errorf("Failed to decompress packet from a client: {}. The server may be out of RAM! The receive failed and the client may be disconnected as a result", e.what());
// return empty -> error
return std::vector<uint8_t>();
}
} else {
return Data;
}
Expand Down
14 changes: 13 additions & 1 deletion src/TServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,19 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
constexpr std::string_view ABG = "ABG:";
if (Packet.size() >= ABG.size() && std::equal(Packet.begin(), Packet.begin() + ABG.size(), ABG.begin(), ABG.end())) {
Packet.erase(Packet.begin(), Packet.begin() + ABG.size());
Packet = DeComp(Packet);
try {
Packet = DeComp(Packet);
} catch (const InvalidDataError& ) {
auto LockedClient = Client.lock();
beammp_errorf("Failed to decompress packet from client {}. The client sent invalid data and will now be disconnected.", LockedClient->GetID());
Network.ClientKick(*LockedClient, "Sent invalid compressed packet (this is likely a bug on your end)");
return;
} catch (const std::runtime_error& e) {
auto LockedClient = Client.lock();
beammp_errorf("Failed to decompress packet from client {}: {}. The server might be out of RAM! The client will now be disconnected.", LockedClient->GetID(), e.what());
Network.ClientKick(*LockedClient, "Decompression failed (likely a server-side problem)");
return;
}
}
if (Packet.empty()) {
return;
Expand Down
Loading