diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-03-27 17:28:22 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-03-27 16:28:48 +0100 |
commit | 4317db7498eaa5a37068052bb0310fbc6a5f78e4 (patch) | |
tree | 894d72f149099fa5b82f0ccfab30cd41db58a16b /Userland/Libraries/LibArchive | |
parent | 1ff6f2b4b266ff90f15d9a462c3b44f88c4c645b (diff) | |
download | serenity-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/Libraries/LibArchive')
-rw-r--r-- | Userland/Libraries/LibArchive/Zip.h | 12 |
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; |