Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79aa9900 authored by Donald Chai's avatar Donald Chai Committed by android-build-merger
Browse files

Merge "Avoid using data descriptors in ZIP files when possible." am:...

Merge "Avoid using data descriptors in ZIP files when possible." am: 69055b5a am: a589dd1e am: 353d0293 am: fbd9760b
am: d939b798

Change-Id: I2a1258cc7c62368ffa55e500b4e858964bb8f322
parents 6a3d7d2c d939b798
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -76,6 +76,10 @@ cc_defaults {
        "liblog",
        "liblog",
    ],
    ],


    // for FRIEND_TEST
    static_libs: ["libgtest_prod"],
    export_static_lib_headers: ["libgtest_prod"],

    export_include_dirs: ["include"],
    export_include_dirs: ["include"],
}
}


+4 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <cstdio>
#include <cstdio>
#include <ctime>
#include <ctime>


#include <gtest/gtest_prod.h>
#include <memory>
#include <memory>
#include <string>
#include <string>
#include <string_view>
#include <string_view>
@@ -165,6 +166,7 @@ class ZipWriter {
  int32_t StoreBytes(FileEntry* file, const void* data, uint32_t len);
  int32_t StoreBytes(FileEntry* file, const void* data, uint32_t len);
  int32_t CompressBytes(FileEntry* file, const void* data, uint32_t len);
  int32_t CompressBytes(FileEntry* file, const void* data, uint32_t len);
  int32_t FlushCompressedBytes(FileEntry* file);
  int32_t FlushCompressedBytes(FileEntry* file);
  bool ShouldUseDataDescriptor() const;


  enum class State {
  enum class State {
    kWritingZip,
    kWritingZip,
@@ -182,4 +184,6 @@ class ZipWriter {


  std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
  std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
  std::vector<uint8_t> buffer_;
  std::vector<uint8_t> buffer_;

  FRIEND_TEST(zipwriter, WriteToUnseekableFile);
};
};
+7 −2
Original line number Original line Diff line number Diff line
@@ -455,6 +455,11 @@ int32_t ZipWriter::FlushCompressedBytes(FileEntry* file) {
  return kNoError;
  return kNoError;
}
}


bool ZipWriter::ShouldUseDataDescriptor() const {
  // Only use a trailing "data descriptor" if the output isn't seekable.
  return !seekable_;
}

int32_t ZipWriter::FinishEntry() {
int32_t ZipWriter::FinishEntry() {
  if (state_ != State::kWritingEntry) {
  if (state_ != State::kWritingEntry) {
    return kInvalidState;
    return kInvalidState;
@@ -467,7 +472,7 @@ int32_t ZipWriter::FinishEntry() {
    }
    }
  }
  }


  if ((current_file_entry_.compression_method & kCompressDeflated) || !seekable_) {
  if (ShouldUseDataDescriptor()) {
    // Some versions of ZIP don't allow STORED data to have a trailing DataDescriptor.
    // Some versions of ZIP don't allow STORED data to have a trailing DataDescriptor.
    // If this file is not seekable, or if the data is compressed, write a DataDescriptor.
    // If this file is not seekable, or if the data is compressed, write a DataDescriptor.
    const uint32_t sig = DataDescriptor::kOptSignature;
    const uint32_t sig = DataDescriptor::kOptSignature;
@@ -515,7 +520,7 @@ int32_t ZipWriter::Finish() {
  for (FileEntry& file : files_) {
  for (FileEntry& file : files_) {
    CentralDirectoryRecord cdr = {};
    CentralDirectoryRecord cdr = {};
    cdr.record_signature = CentralDirectoryRecord::kSignature;
    cdr.record_signature = CentralDirectoryRecord::kSignature;
    if ((file.compression_method & kCompressDeflated) || !seekable_) {
    if (ShouldUseDataDescriptor()) {
      cdr.gpb_flags |= kGPBDDFlagMask;
      cdr.gpb_flags |= kGPBDDFlagMask;
    }
    }
    cdr.compression_method = file.compression_method;
    cdr.compression_method = file.compression_method;
+24 −0
Original line number Original line Diff line number Diff line
@@ -243,6 +243,7 @@ TEST_F(zipwriter, WriteCompressedZipWithOneFile) {
  ZipEntry data;
  ZipEntry data;
  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
  EXPECT_EQ(kCompressDeflated, data.method);
  EXPECT_EQ(kCompressDeflated, data.method);
  EXPECT_EQ(0u, data.has_data_descriptor);
  ASSERT_EQ(4u, data.uncompressed_length);
  ASSERT_EQ(4u, data.uncompressed_length);
  ASSERT_TRUE(AssertFileEntryContentsEq("helo", handle, &data));
  ASSERT_TRUE(AssertFileEntryContentsEq("helo", handle, &data));


@@ -351,6 +352,29 @@ TEST_F(zipwriter, BackupRemovesTheLastFile) {
  CloseArchive(handle);
  CloseArchive(handle);
}
}


TEST_F(zipwriter, WriteToUnseekableFile) {
  const char* expected = "hello";
  ZipWriter writer(file_);
  writer.seekable_ = false;

  ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
  ASSERT_EQ(0, writer.WriteBytes(expected, strlen(expected)));
  ASSERT_EQ(0, writer.FinishEntry());
  ASSERT_EQ(0, writer.Finish());
  ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));

  ZipArchiveHandle handle;
  ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
  ZipEntry data;
  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
  EXPECT_EQ(kCompressStored, data.method);
  EXPECT_EQ(1u, data.has_data_descriptor);
  EXPECT_EQ(strlen(expected), data.compressed_length);
  ASSERT_EQ(strlen(expected), data.uncompressed_length);
  ASSERT_TRUE(AssertFileEntryContentsEq(expected, handle, &data));
  CloseArchive(handle);
}

TEST_F(zipwriter, TruncateFileAfterBackup) {
TEST_F(zipwriter, TruncateFileAfterBackup) {
  ZipWriter writer(file_);
  ZipWriter writer(file_);