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
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 8f9774f..7658d5c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -1009,19 +1009,17 @@
 // 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 @@
   // 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 @@
       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 @@
     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 @@
       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 @@
     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 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 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) {