Allow ExtractToMemory to accept an empty buffer for empty entries

We don't actually need to extract the empty entries. Since the old
code support extracting the empty entry to a empty buffer, add the
support back in ExtractToMemory.

Bug: 153393683
Test: unittests pass

Change-Id: Idb9f0f4e6e4ffd4b44b80ddd3f54069bb7cedd7b
This commit is contained in:
Tianjie 2020-04-07 00:12:54 -07:00
parent edf8335c72
commit 088c403e23
2 changed files with 21 additions and 22 deletions

View File

@ -1009,19 +1009,17 @@ int32_t Next(void* cookie, ZipEntry64* data, std::string_view* name) {
// the data appended to it.
class MemoryWriter : public zip_archive::Writer {
public:
static MemoryWriter Create(uint8_t* buf, size_t size, const ZipEntry64* entry) {
static std::unique_ptr<MemoryWriter> Create(uint8_t* buf, size_t size, const ZipEntry64* entry) {
const uint64_t declared_length = entry->uncompressed_length;
if (declared_length > size) {
ALOGW("Zip: file size %" PRIu64 " is larger than the buffer size %zu.", declared_length,
size);
return MemoryWriter{nullptr, 0};
return nullptr;
}
return MemoryWriter(buf, size);
return std::unique_ptr<MemoryWriter>(new MemoryWriter(buf, size));
}
bool IsValid() const { return buf_ != nullptr; }
virtual bool Append(uint8_t* buf, size_t buf_size) override {
if (size_ < buf_size || bytes_written_ > size_ - buf_size) {
ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", size_,
@ -1053,17 +1051,17 @@ class FileWriter : public zip_archive::Writer {
// block device).
//
// Returns a valid FileWriter on success, |nullptr| if an error occurred.
static FileWriter Create(int fd, const ZipEntry64* entry) {
static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry64* entry) {
const uint64_t declared_length = entry->uncompressed_length;
const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
if (current_offset == -1) {
ALOGW("Zip: unable to seek to current location on fd %d: %s", fd, strerror(errno));
return FileWriter{};
return nullptr;
}
if (declared_length > SIZE_MAX || declared_length > INT64_MAX) {
ALOGW("Zip: file size %" PRIu64 " is too large to extract.", declared_length);
return FileWriter{};
return nullptr;
}
#if defined(__linux__)
@ -1081,7 +1079,7 @@ class FileWriter : public zip_archive::Writer {
if (result == -1 && errno == ENOSPC) {
ALOGW("Zip: unable to allocate %" PRIu64 " bytes at offset %" PRId64 ": %s",
declared_length, static_cast<int64_t>(current_offset), strerror(errno));
return FileWriter{};
return nullptr;
}
}
#endif // __linux__
@ -1089,7 +1087,7 @@ class FileWriter : public zip_archive::Writer {
struct stat sb;
if (fstat(fd, &sb) == -1) {
ALOGW("Zip: unable to fstat file: %s", strerror(errno));
return FileWriter{};
return nullptr;
}
// Block device doesn't support ftruncate(2).
@ -1098,11 +1096,11 @@ class FileWriter : public zip_archive::Writer {
if (result == -1) {
ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
static_cast<int64_t>(declared_length + current_offset), strerror(errno));
return FileWriter{};
return nullptr;
}
}
return FileWriter(fd, declared_length);
return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
}
FileWriter(FileWriter&& other) noexcept
@ -1112,8 +1110,6 @@ class FileWriter : public zip_archive::Writer {
other.fd_ = -1;
}
bool IsValid() const { return fd_ != -1; }
virtual bool Append(uint8_t* buf, size_t buf_size) override {
if (declared_length_ < buf_size || total_bytes_written_ > declared_length_ - buf_size) {
ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", declared_length_,
@ -1365,11 +1361,11 @@ int32_t ExtractToMemory(ZipArchiveHandle archive, const ZipEntry* entry, uint8_t
int32_t ExtractToMemory(ZipArchiveHandle archive, const ZipEntry64* entry, uint8_t* begin,
size_t size) {
auto writer = MemoryWriter::Create(begin, size, entry);
if (!writer.IsValid()) {
if (!writer) {
return kIoError;
}
return ExtractToWriter(archive, entry, &writer);
return ExtractToWriter(archive, entry, writer.get());
}
int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry* entry, int fd) {
@ -1379,11 +1375,11 @@ int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry* entry, int
int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry64* entry, int fd) {
auto writer = FileWriter::Create(fd, entry);
if (!writer.IsValid()) {
if (!writer) {
return kIoError;
}
return ExtractToWriter(archive, entry, &writer);
return ExtractToWriter(archive, entry, writer.get());
}
int GetFileDescriptor(const ZipArchiveHandle archive) {

View File

@ -344,8 +344,8 @@ TEST(ziparchive, FindEntry) {
// Known facts about a.txt, from zipinfo -v.
ASSERT_EQ(63, data.offset);
ASSERT_EQ(kCompressDeflated, data.method);
ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
ASSERT_EQ(17u, data.uncompressed_length);
ASSERT_EQ(13u, data.compressed_length);
ASSERT_EQ(0x950821c5, data.crc32);
ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
@ -505,9 +505,12 @@ TEST(ziparchive, EmptyEntries) {
ZipEntry64 entry;
ASSERT_EQ(0, FindEntry(handle, "empty.txt", &entry));
ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
ASSERT_EQ(0u, entry.uncompressed_length);
// Extraction to a 1 byte buffer should succeed.
uint8_t buffer[1];
ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
// Extraction to an empty buffer should succeed.
ASSERT_EQ(0, ExtractToMemory(handle, &entry, nullptr, 0));
TemporaryFile tmp_output_file;
ASSERT_NE(-1, tmp_output_file.fd);
@ -782,7 +785,7 @@ static void ExtractEntryToMemory(const std::vector<uint8_t>& zip_data,
// "abdcdefghijk").
ZipEntry64 entry;
ASSERT_EQ(0, FindEntry(handle, "name", &entry));
ASSERT_EQ(static_cast<uint32_t>(12), entry.uncompressed_length);
ASSERT_EQ(12u, entry.uncompressed_length);
entry_out->resize(12);
(*error_code_out) = ExtractToMemory(handle, &entry, &((*entry_out)[0]), 12);