mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:17:34 +00:00
LibCompress: Convert GzipDecompressor from recursive to iterative
This way a gzip compressed file that contains a large amount of small blocks wont cause a stack overflow.
This commit is contained in:
parent
00bbe76c94
commit
b3b8c01ebf
1 changed files with 77 additions and 69 deletions
|
@ -70,20 +70,24 @@ GzipDecompressor::~GzipDecompressor()
|
||||||
// FIXME: Again, there are surely a ton of bugs because the code doesn't check for read errors.
|
// FIXME: Again, there are surely a ton of bugs because the code doesn't check for read errors.
|
||||||
size_t GzipDecompressor::read(Bytes bytes)
|
size_t GzipDecompressor::read(Bytes bytes)
|
||||||
{
|
{
|
||||||
|
size_t total_read = 0;
|
||||||
|
while (total_read < bytes.size()) {
|
||||||
if (has_any_error() || m_eof)
|
if (has_any_error() || m_eof)
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
|
auto slice = bytes.slice(total_read);
|
||||||
|
|
||||||
if (m_current_member.has_value()) {
|
if (m_current_member.has_value()) {
|
||||||
size_t nread = current_member().m_stream.read(bytes);
|
size_t nread = current_member().m_stream.read(slice);
|
||||||
current_member().m_checksum.update(bytes.trim(nread));
|
current_member().m_checksum.update(slice.trim(nread));
|
||||||
current_member().m_nread += nread;
|
current_member().m_nread += nread;
|
||||||
|
|
||||||
if (current_member().m_stream.handle_any_error()) {
|
if (current_member().m_stream.handle_any_error()) {
|
||||||
set_fatal_error();
|
set_fatal_error();
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nread < bytes.size()) {
|
if (nread < slice.size()) {
|
||||||
LittleEndian<u32> crc32, input_size;
|
LittleEndian<u32> crc32, input_size;
|
||||||
m_input_stream >> crc32 >> input_size;
|
m_input_stream >> crc32 >> input_size;
|
||||||
|
|
||||||
|
@ -91,30 +95,32 @@ size_t GzipDecompressor::read(Bytes bytes)
|
||||||
// FIXME: Somehow the checksum is incorrect?
|
// FIXME: Somehow the checksum is incorrect?
|
||||||
|
|
||||||
set_fatal_error();
|
set_fatal_error();
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input_size != current_member().m_nread) {
|
if (input_size != current_member().m_nread) {
|
||||||
set_fatal_error();
|
set_fatal_error();
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_member.clear();
|
m_current_member.clear();
|
||||||
|
|
||||||
return nread + read(bytes.slice(nread));
|
total_read += nread;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nread;
|
total_read += nread;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
m_partial_header_offset += m_input_stream.read(Bytes { m_partial_header, sizeof(BlockHeader) }.slice(m_partial_header_offset));
|
m_partial_header_offset += m_input_stream.read(Bytes { m_partial_header, sizeof(BlockHeader) }.slice(m_partial_header_offset));
|
||||||
|
|
||||||
if (m_input_stream.handle_any_error() || m_input_stream.unreliable_eof()) {
|
if (m_input_stream.handle_any_error() || m_input_stream.unreliable_eof()) {
|
||||||
m_eof = true;
|
m_eof = true;
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_partial_header_offset < sizeof(BlockHeader)) {
|
if (m_partial_header_offset < sizeof(BlockHeader)) {
|
||||||
return 0; // partial header read
|
break; // partial header read
|
||||||
}
|
}
|
||||||
m_partial_header_offset = 0;
|
m_partial_header_offset = 0;
|
||||||
|
|
||||||
|
@ -122,7 +128,7 @@ size_t GzipDecompressor::read(Bytes bytes)
|
||||||
|
|
||||||
if (!header.valid_magic_number() || !header.supported_by_implementation()) {
|
if (!header.valid_magic_number() || !header.supported_by_implementation()) {
|
||||||
set_fatal_error();
|
set_fatal_error();
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.flags & Flags::FEXTRA) {
|
if (header.flags & Flags::FEXTRA) {
|
||||||
|
@ -148,9 +154,11 @@ size_t GzipDecompressor::read(Bytes bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_member.emplace(header, m_input_stream);
|
m_current_member.emplace(header, m_input_stream);
|
||||||
return read(bytes);
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return total_read;
|
||||||
|
}
|
||||||
|
|
||||||
bool GzipDecompressor::read_or_error(Bytes bytes)
|
bool GzipDecompressor::read_or_error(Bytes bytes)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue