LibArchive: Bounds check header offsets in Zip Parser

Since the central directory offset in the end of central directory
record and the local file offset in each central directory header
are user-controlled arbitary data, we have to bounds check them
before using them.
This commit is contained in:
Idan Horowitz 2021-03-27 21:32:15 +03:00 committed by Andreas Kling
parent f046654477
commit 1ac661515e
Notes: sideshowbarker 2024-07-18 21:01:02 +09:00

View file

@ -60,6 +60,8 @@ Optional<Zip> Zip::try_create(const ReadonlyBytes& buffer)
size_t member_offset = end_of_central_directory.central_directory_offset; size_t member_offset = end_of_central_directory.central_directory_offset;
for (size_t i = 0; i < end_of_central_directory.total_records_count; i++) { for (size_t i = 0; i < end_of_central_directory.total_records_count; i++) {
CentralDirectoryRecord central_directory_record {}; CentralDirectoryRecord central_directory_record {};
if (member_offset > buffer.size())
return {};
if (!central_directory_record.read(buffer.slice(member_offset))) if (!central_directory_record.read(buffer.slice(member_offset)))
return {}; return {};
if (central_directory_record.general_purpose_flags & 1) if (central_directory_record.general_purpose_flags & 1)
@ -75,6 +77,8 @@ Optional<Zip> Zip::try_create(const ReadonlyBytes& buffer)
if (memchr(central_directory_record.name, 0, central_directory_record.name_length) != nullptr) if (memchr(central_directory_record.name, 0, central_directory_record.name_length) != nullptr)
return {}; return {};
LocalFileHeader local_file_header {}; LocalFileHeader local_file_header {};
if (central_directory_record.local_file_header_offset > buffer.size())
return {};
if (!local_file_header.read(buffer.slice(central_directory_record.local_file_header_offset))) if (!local_file_header.read(buffer.slice(central_directory_record.local_file_header_offset)))
return {}; return {};
if (buffer.size() - (local_file_header.compressed_data - buffer.data()) < central_directory_record.compressed_size) if (buffer.size() - (local_file_header.compressed_data - buffer.data()) < central_directory_record.compressed_size)