mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-08-16 16:26:26 +00:00
refactor decompression limits and resizing
This commit is contained in:
parent
8b21b6cef3
commit
0950d367d4
@ -387,13 +387,16 @@ void SplitString(const std::string& str, const char delim, std::vector<std::stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr size_t STARTING_MAX_DECOMPRESSION_BUFFER_SIZE = 15 * 1024 * 1024;
|
||||||
|
static constexpr size_t MAX_DECOMPRESSION_BUFFER_SIZE = 30 * 1024 * 1024;
|
||||||
|
|
||||||
std::vector<uint8_t> DeComp(std::span<const uint8_t> input) {
|
std::vector<uint8_t> DeComp(std::span<const uint8_t> input) {
|
||||||
beammp_debugf("got {} bytes of input data", input.size());
|
beammp_debugf("got {} bytes of input data", input.size());
|
||||||
|
|
||||||
// start with a decompression buffer of 5x the input size, clamped to a maximum of 15 MB.
|
// start with a decompression buffer of 5x the input size, clamped to a maximum of 15 MB.
|
||||||
// this buffer can and will grow, but we don't want to start it too large. A 5x compression ratio
|
// this buffer can and will grow, but we don't want to start it too large. A 5x compression ratio
|
||||||
// is pretty optimistic.
|
// is pretty optimistic.
|
||||||
std::vector<uint8_t> output_buffer(std::min<size_t>(input.size() * 5, 15 * 1024 * 1024));
|
std::vector<uint8_t> output_buffer(std::min<size_t>(input.size() * 5, STARTING_MAX_DECOMPRESSION_BUFFER_SIZE));
|
||||||
|
|
||||||
uLongf output_size = output_buffer.size();
|
uLongf output_size = output_buffer.size();
|
||||||
|
|
||||||
@ -404,14 +407,17 @@ std::vector<uint8_t> DeComp(std::span<const uint8_t> input) {
|
|||||||
reinterpret_cast<const Bytef*>(input.data()),
|
reinterpret_cast<const Bytef*>(input.data()),
|
||||||
static_cast<uLongf>(input.size()));
|
static_cast<uLongf>(input.size()));
|
||||||
if (res == Z_BUF_ERROR) {
|
if (res == Z_BUF_ERROR) {
|
||||||
// We assume that a reasonable maximum size for decompressed packets is 30 MB.
|
// We assume that a reasonable maximum size for decompressed packets exists. We want to avoid
|
||||||
// If this were to be an issue, this could be made configurable, however clients have a similar
|
// a client effectively "zip bombing" us by sending a lot of small packets which decompress
|
||||||
|
// into huge data.
|
||||||
|
// If this limit were to be an issue, this could be made configurable, however clients have a similar
|
||||||
// limit. For that reason, we just reject packets which decompress into too much data.
|
// limit. For that reason, we just reject packets which decompress into too much data.
|
||||||
if (output_buffer.size() > 30 * 1024 * 1024) {
|
if (output_buffer.size() > MAX_DECOMPRESSION_BUFFER_SIZE) {
|
||||||
throw std::runtime_error("decompressed packet size of 30 MB exceeded");
|
throw std::runtime_error(fmt::format("decompressed packet size of {} bytes exceeded", MAX_DECOMPRESSION_BUFFER_SIZE));
|
||||||
}
|
}
|
||||||
beammp_warn("zlib uncompress() failed, trying with 2x buffer size of " + std::to_string(output_buffer.size() * 2));
|
// if decompression fails, we double the buffer size (up to the allowed limit) and try again
|
||||||
output_buffer.resize(output_buffer.size() * 2);
|
output_buffer.resize(std::max<size_t>(output_buffer.size() * 2, MAX_DECOMPRESSION_BUFFER_SIZE));
|
||||||
|
beammp_warnf("zlib uncompress() failed, trying with a larger buffer size of {}", output_buffer.size());
|
||||||
output_size = output_buffer.size();
|
output_size = output_buffer.size();
|
||||||
} else if (res != Z_OK) {
|
} else if (res != Z_OK) {
|
||||||
beammp_error("zlib uncompress() failed: " + std::to_string(res));
|
beammp_error("zlib uncompress() failed: " + std::to_string(res));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user