summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-03-27 17:28:22 +0300
committerAndreas Kling <kling@serenityos.org>2021-03-27 16:28:48 +0100
commit4317db7498eaa5a37068052bb0310fbc6a5f78e4 (patch)
tree894d72f149099fa5b82f0ccfab30cd41db58a16b /Userland
parent1ff6f2b4b266ff90f15d9a462c3b44f88c4c645b (diff)
downloadserenity-4317db7498eaa5a37068052bb0310fbc6a5f78e4.zip
LibArchive: Make bounds checks stricter in the Zip parser
We now also check we have enough space in the incoming buffer for the various signatures and optional (length specified) fields. This helps prevents a possible heap overflow read.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibArchive/Zip.h12
1 files changed, 9 insertions, 3 deletions
diff --git a/Userland/Libraries/LibArchive/Zip.h b/Userland/Libraries/LibArchive/Zip.h
index ac835b8bfa..66a25acf72 100644
--- a/Userland/Libraries/LibArchive/Zip.h
+++ b/Userland/Libraries/LibArchive/Zip.h
@@ -52,11 +52,13 @@ struct [[gnu::packed]] EndOfCentralDirectory {
bool read(ReadonlyBytes buffer)
{
auto fields_size = sizeof(EndOfCentralDirectory) - sizeof(u8*);
- if (buffer.size() < fields_size)
+ if (buffer.size() < sizeof(end_of_central_directory_signature) + fields_size)
return false;
if (memcmp(buffer.data(), end_of_central_directory_signature, sizeof(end_of_central_directory_signature)) != 0)
return false;
memcpy(reinterpret_cast<void*>(&disk_number), buffer.data() + sizeof(end_of_central_directory_signature), fields_size);
+ if (buffer.size() < sizeof(end_of_central_directory_signature) + fields_size + comment_length)
+ return false;
comment = buffer.data() + sizeof(end_of_central_directory_signature) + fields_size;
return true;
}
@@ -101,11 +103,13 @@ struct [[gnu::packed]] CentralDirectoryRecord {
bool read(ReadonlyBytes buffer)
{
auto fields_size = sizeof(CentralDirectoryRecord) - (sizeof(u8*) * 3);
- if (buffer.size() < fields_size)
+ if (buffer.size() < sizeof(central_directory_record_signature) + fields_size)
return false;
if (memcmp(buffer.data(), central_directory_record_signature, sizeof(central_directory_record_signature)) != 0)
return false;
memcpy(reinterpret_cast<void*>(&made_by_version), buffer.data() + sizeof(central_directory_record_signature), fields_size);
+ if (buffer.size() < sizeof(end_of_central_directory_signature) + fields_size + comment_length + name_length + extra_data_length)
+ return false;
name = buffer.data() + sizeof(central_directory_record_signature) + fields_size;
extra_data = name + name_length;
comment = extra_data + extra_data_length;
@@ -165,11 +169,13 @@ struct [[gnu::packed]] LocalFileHeader {
bool read(ReadonlyBytes buffer)
{
auto fields_size = sizeof(LocalFileHeader) - (sizeof(u8*) * 3);
- if (buffer.size() < fields_size)
+ if (buffer.size() < sizeof(local_file_header_signature) + fields_size)
return false;
if (memcmp(buffer.data(), local_file_header_signature, sizeof(local_file_header_signature)) != 0)
return false;
memcpy(reinterpret_cast<void*>(&minimum_version), buffer.data() + sizeof(local_file_header_signature), fields_size);
+ if (buffer.size() < sizeof(end_of_central_directory_signature) + fields_size + name_length + extra_data_length + compressed_size)
+ return false;
name = buffer.data() + sizeof(local_file_header_signature) + fields_size;
extra_data = name + name_length;
compressed_data = extra_data + extra_data_length;