From acc9be9f7d6d65278fa912ca5d9af5762e91eb70 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 12 May 2022 21:54:08 +0200 Subject: [PATCH] LibArchive: Use named members for ZIP general purpose flags This fixes the faulty bit check that misclassified ZIPs as having data descriptors. --- Userland/Libraries/LibArchive/Zip.cpp | 8 ++++---- Userland/Libraries/LibArchive/Zip.h | 26 ++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Userland/Libraries/LibArchive/Zip.cpp b/Userland/Libraries/LibArchive/Zip.cpp index 71d173bab37..024e139715d 100644 --- a/Userland/Libraries/LibArchive/Zip.cpp +++ b/Userland/Libraries/LibArchive/Zip.cpp @@ -51,9 +51,9 @@ Optional Zip::try_create(ReadonlyBytes buffer) return {}; if (!central_directory_record.read(buffer.slice(member_offset))) return {}; - if (central_directory_record.general_purpose_flags & 1) + if (central_directory_record.general_purpose_flags.encrypted) return {}; // TODO: support encrypted zip members - if (central_directory_record.general_purpose_flags & 3) + if (central_directory_record.general_purpose_flags.data_descriptor) return {}; // TODO: support zip data descriptors if (central_directory_record.compression_method != ZipCompressionMethod::Store && central_directory_record.compression_method != ZipCompressionMethod::Deflate) return {}; // TODO: support obsolete zip compression methods @@ -128,7 +128,7 @@ void ZipOutputStream::add_member(ZipMember const& member) LocalFileHeader local_file_header { .minimum_version = minimum_version_needed(member.compression_method), - .general_purpose_flags = 0, + .general_purpose_flags = { .flags = 0 }, .compression_method = static_cast(member.compression_method), .modification_time = 0, // TODO: support modification time .modification_date = 0, @@ -156,7 +156,7 @@ void ZipOutputStream::finish() CentralDirectoryRecord central_directory_record { .made_by_version = zip_version, .minimum_version = zip_version, - .general_purpose_flags = 0, + .general_purpose_flags = { .flags = 0 }, .compression_method = member.compression_method, .modification_time = 0, // TODO: support modification time .modification_date = 0, diff --git a/Userland/Libraries/LibArchive/Zip.h b/Userland/Libraries/LibArchive/Zip.h index 95913f7b5ca..33c687c84e1 100644 --- a/Userland/Libraries/LibArchive/Zip.h +++ b/Userland/Libraries/LibArchive/Zip.h @@ -82,6 +82,24 @@ enum class ZipCompressionMethod : u16 { Deflate = 8 }; +union ZipGeneralPurposeFlags { + u16 flags; + struct { + u16 encrypted : 1; + u16 compression_options : 2; + u16 data_descriptor : 1; + u16 enhanced_deflation : 1; + u16 compressed_patched_data : 1; + u16 strong_encryption : 1; + u16 : 4; + u16 language_encoding : 1; + u16 : 1; + u16 masked_data_values : 1; + u16 : 2; + }; +}; +static_assert(sizeof(ZipGeneralPurposeFlags) == sizeof(u16)); + OutputStream& operator<<(OutputStream& stream, ZipCompressionMethod method); struct [[gnu::packed]] CentralDirectoryRecord { @@ -89,7 +107,7 @@ struct [[gnu::packed]] CentralDirectoryRecord { u16 made_by_version; u16 minimum_version; - u16 general_purpose_flags; + ZipGeneralPurposeFlags general_purpose_flags; ZipCompressionMethod compression_method; u16 modification_time; u16 modification_date; @@ -125,7 +143,7 @@ struct [[gnu::packed]] CentralDirectoryRecord { stream.write_or_error(signature); stream << made_by_version; stream << minimum_version; - stream << general_purpose_flags; + stream << general_purpose_flags.flags; stream << compression_method; stream << modification_time; stream << modification_date; @@ -158,7 +176,7 @@ struct [[gnu::packed]] LocalFileHeader { static constexpr Array signature = { 0x50, 0x4b, 0x03, 0x04 }; // 'PK\x03\x04' u16 minimum_version; - u16 general_purpose_flags; + ZipGeneralPurposeFlags general_purpose_flags; u16 compression_method; u16 modification_time; u16 modification_date; @@ -188,7 +206,7 @@ struct [[gnu::packed]] LocalFileHeader { { stream.write_or_error(signature); stream << minimum_version; - stream << general_purpose_flags; + stream << general_purpose_flags.flags; stream << compression_method; stream << modification_time; stream << modification_date;