LibArchive: Make TarInputStream::advance report errors
Fixes this bug that was reported by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52862
This commit is contained in:
parent
26a4327b06
commit
c88d8a21cc
Notes:
sideshowbarker
2024-07-17 04:30:53 +09:00
Author: https://github.com/implicitfield Commit: https://github.com/SerenityOS/serenity/commit/c88d8a21cc Pull-request: https://github.com/SerenityOS/serenity/pull/16008 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/timschumi
4 changed files with 18 additions and 8 deletions
|
@ -16,7 +16,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||||
if (!tar_stream.valid())
|
if (!tar_stream.valid())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (; !tar_stream.finished(); tar_stream.advance()) {
|
while (!tar_stream.finished()) {
|
||||||
auto const& header = tar_stream.header();
|
auto const& header = tar_stream.header();
|
||||||
|
|
||||||
if (!header.content_is_like_extended_header())
|
if (!header.content_is_like_extended_header())
|
||||||
|
@ -33,6 +33,10 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto maybe_error = tar_stream.advance();
|
||||||
|
if (maybe_error.is_error())
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -71,7 +71,7 @@ TarInputStream::TarInputStream(InputStream& stream)
|
||||||
{
|
{
|
||||||
if (!m_stream.read_or_error(Bytes(&m_header, sizeof(m_header)))) {
|
if (!m_stream.read_or_error(Bytes(&m_header, sizeof(m_header)))) {
|
||||||
m_finished = true;
|
m_finished = true;
|
||||||
m_stream.handle_any_error(); // clear out errors so we dont assert
|
m_stream.handle_any_error(); // clear out errors so we don't assert
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VERIFY(m_stream.discard_or_error(block_size - sizeof(TarFileHeader)));
|
VERIFY(m_stream.discard_or_error(block_size - sizeof(TarFileHeader)));
|
||||||
|
@ -82,10 +82,10 @@ static constexpr unsigned long block_ceiling(unsigned long offset)
|
||||||
return block_size * (1 + ((offset - 1) / block_size));
|
return block_size * (1 + ((offset - 1) / block_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TarInputStream::advance()
|
ErrorOr<void> TarInputStream::advance()
|
||||||
{
|
{
|
||||||
if (m_finished)
|
if (m_finished)
|
||||||
return;
|
return Error::from_string_literal("Attempted to read a finished stream");
|
||||||
|
|
||||||
m_generation++;
|
m_generation++;
|
||||||
VERIFY(m_stream.discard_or_error(block_ceiling(m_header.size()) - m_file_offset));
|
VERIFY(m_stream.discard_or_error(block_ceiling(m_header.size()) - m_file_offset));
|
||||||
|
@ -93,14 +93,16 @@ void TarInputStream::advance()
|
||||||
|
|
||||||
if (!m_stream.read_or_error(Bytes(&m_header, sizeof(m_header)))) {
|
if (!m_stream.read_or_error(Bytes(&m_header, sizeof(m_header)))) {
|
||||||
m_finished = true;
|
m_finished = true;
|
||||||
return;
|
m_stream.handle_any_error(); // clear out errors so we don't assert
|
||||||
|
return Error::from_string_literal("Failed to read the header");
|
||||||
}
|
}
|
||||||
if (!valid()) {
|
if (!valid()) {
|
||||||
m_finished = true;
|
m_finished = true;
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(m_stream.discard_or_error(block_size - sizeof(TarFileHeader)));
|
VERIFY(m_stream.discard_or_error(block_size - sizeof(TarFileHeader)));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TarInputStream::valid() const
|
bool TarInputStream::valid() const
|
||||||
|
|
|
@ -34,7 +34,7 @@ private:
|
||||||
class TarInputStream {
|
class TarInputStream {
|
||||||
public:
|
public:
|
||||||
TarInputStream(InputStream&);
|
TarInputStream(InputStream&);
|
||||||
void advance();
|
ErrorOr<void> advance();
|
||||||
bool finished() const { return m_finished; }
|
bool finished() const { return m_finished; }
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
TarFileHeader const& header() const { return m_header; }
|
TarFileHeader const& header() const { return m_header; }
|
||||||
|
|
|
@ -98,7 +98,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
for (; !tar_stream.finished(); tar_stream.advance()) {
|
while (!tar_stream.finished()) {
|
||||||
Archive::TarFileHeader const& header = tar_stream.header();
|
Archive::TarFileHeader const& header = tar_stream.header();
|
||||||
|
|
||||||
// Handle meta-entries earlier to avoid consuming the file content stream.
|
// Handle meta-entries earlier to avoid consuming the file content stream.
|
||||||
|
@ -198,6 +198,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
// Non-global headers should be cleared after every file.
|
// Non-global headers should be cleared after every file.
|
||||||
local_overrides.clear();
|
local_overrides.clear();
|
||||||
|
|
||||||
|
auto maybe_error = tar_stream.advance();
|
||||||
|
if (maybe_error.is_error())
|
||||||
|
return maybe_error.error();
|
||||||
}
|
}
|
||||||
file_stream.close();
|
file_stream.close();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue