Merge "Ziparchive: Enable -Wconversion"
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index bc1543b..858c0bb 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -26,6 +26,8 @@
         // Incorrectly warns when C++11 empty brace {} initializer is used.
         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
         "-Wno-missing-field-initializers",
+        "-Wconversion",
+        "-Wno-sign-conversion",
     ],
 
     // Enable -Wold-style-cast only for non-Windows targets.  _islower_l,
diff --git a/libziparchive/entry_name_utils-inl.h b/libziparchive/entry_name_utils-inl.h
index 1714586..10311b5 100644
--- a/libziparchive/entry_name_utils-inl.h
+++ b/libziparchive/entry_name_utils-inl.h
@@ -20,9 +20,15 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <limits>
+
 // Check if |length| bytes at |entry_name| constitute a valid entry name.
-// Entry names must be valid UTF-8 and must not contain '0'.
+// Entry names must be valid UTF-8 and must not contain '0'. They also must
+// fit into the central directory record.
 inline bool IsValidEntryName(const uint8_t* entry_name, const size_t length) {
+  if (length > std::numeric_limits<uint16_t>::max()) {
+    return false;
+  }
   for (size_t i = 0; i < length; ++i) {
     const uint8_t byte = entry_name[i];
     if (byte == 0) {
@@ -35,7 +41,8 @@
       return false;
     } else {
       // 2-5 byte sequences.
-      for (uint8_t first = (byte & 0x7f) << 1; first & 0x80; first = (first & 0x7f) << 1) {
+      for (uint8_t first = static_cast<uint8_t>((byte & 0x7f) << 1); first & 0x80;
+           first = static_cast<uint8_t>((first & 0x7f) << 1)) {
         ++i;
 
         // Missing continuation byte..
diff --git a/libziparchive/include/ziparchive/zip_writer.h b/libziparchive/include/ziparchive/zip_writer.h
index f6c8427..bd44fdb 100644
--- a/libziparchive/include/ziparchive/zip_writer.h
+++ b/libziparchive/include/ziparchive/zip_writer.h
@@ -76,7 +76,7 @@
     uint32_t uncompressed_size;
     uint16_t last_mod_time;
     uint16_t last_mod_date;
-    uint32_t padding_length;
+    uint16_t padding_length;
     off64_t local_file_header_offset;
   };
 
@@ -161,8 +161,8 @@
 
   int32_t HandleError(int32_t error_code);
   int32_t PrepareDeflate();
-  int32_t StoreBytes(FileEntry* file, const void* data, size_t len);
-  int32_t CompressBytes(FileEntry* file, const void* data, size_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 FlushCompressedBytes(FileEntry* file);
 
   enum class State {
diff --git a/libziparchive/unzip.cpp b/libziparchive/unzip.cpp
index cc059d8..c6def73 100644
--- a/libziparchive/unzip.cpp
+++ b/libziparchive/unzip.cpp
@@ -85,7 +85,7 @@
 
 static int CompressionRatio(int64_t uncompressed, int64_t compressed) {
   if (uncompressed == 0) return 0;
-  return (100LL * (uncompressed - compressed)) / uncompressed;
+  return static_cast<int>((100LL * (uncompressed - compressed)) / uncompressed);
 }
 
 static void MaybeShowHeader() {
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index e1ec47a..596786a 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -146,7 +146,7 @@
 /*
  * Add a new entry to the hash table.
  */
-static int32_t AddToHash(ZipStringOffset* hash_table, const uint64_t hash_table_size,
+static int32_t AddToHash(ZipStringOffset* hash_table, const uint32_t hash_table_size,
                          const ZipString& name, const uint8_t* start) {
   const uint64_t hash = ComputeHash(name);
   uint32_t ent = hash & (hash_table_size - 1);
@@ -214,7 +214,7 @@
 }
 
 static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
-                                    off64_t file_length, off64_t read_amount,
+                                    off64_t file_length, uint32_t read_amount,
                                     uint8_t* scan_buffer) {
   const off64_t search_start = file_length - read_amount;
 
@@ -230,7 +230,8 @@
    * doing an initial minimal read; if we don't find it, retry with a
    * second read as above.)
    */
-  int i = read_amount - sizeof(EocdRecord);
+  CHECK_LE(read_amount, std::numeric_limits<int32_t>::max());
+  int32_t i = read_amount - sizeof(EocdRecord);
   for (; i >= 0; i--) {
     if (scan_buffer[i] == 0x50) {
       uint32_t* sig_addr = reinterpret_cast<uint32_t*>(&scan_buffer[i]);
@@ -333,9 +334,9 @@
    *
    * We start by pulling in the last part of the file.
    */
-  off64_t read_amount = kMaxEOCDSearch;
+  uint32_t read_amount = kMaxEOCDSearch;
   if (file_length < read_amount) {
-    read_amount = file_length;
+    read_amount = static_cast<uint32_t>(file_length);
   }
 
   std::vector<uint8_t> scan_buffer(read_amount);
@@ -532,7 +533,7 @@
   return 0;
 }
 
-static int32_t FindEntry(const ZipArchive* archive, const int ent, ZipEntry* data) {
+static int32_t FindEntry(const ZipArchive* archive, const int32_t ent, ZipEntry* data) {
   const uint16_t nameLen = archive->hash_table[ent].name_length;
 
   // Recover the start of the central directory entry from the filename
@@ -751,9 +752,10 @@
                                    archive->central_directory.GetBasePtr());
   if (ent < 0) {
     ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
-    return ent;
+    return static_cast<int32_t>(ent);  // kEntryNotFound is safe to truncate.
   }
-  return FindEntry(archive, ent, data);
+  // We know there are at most hast_table_size entries, safe to truncate.
+  return FindEntry(archive, static_cast<uint32_t>(ent), data);
 }
 
 int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
@@ -836,7 +838,6 @@
       return FileWriter{};
     }
 
-    int result = 0;
 #if defined(__linux__)
     if (declared_length > 0) {
       // Make sure we have enough space on the volume to extract the compressed
@@ -848,7 +849,7 @@
       // EOPNOTSUPP error when issued in other filesystems.
       // Hence, check for the return error code before concluding that the
       // disk does not have enough space.
-      result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
+      long result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
       if (result == -1 && errno == ENOSPC) {
         ALOGW("Zip: unable to allocate %" PRId64 " bytes at offset %" PRId64 ": %s",
               static_cast<int64_t>(declared_length), static_cast<int64_t>(current_offset),
@@ -866,7 +867,7 @@
 
     // Block device doesn't support ftruncate(2).
     if (!S_ISBLK(sb.st_mode)) {
-      result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+      long result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
       if (result == -1) {
         ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
               static_cast<int64_t>(declared_length + current_offset), strerror(errno));
@@ -985,16 +986,16 @@
   std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
 
   const bool compute_crc = (crc_out != nullptr);
-  uint64_t crc = 0;
+  uLong crc = 0;
   uint32_t remaining_bytes = compressed_length;
   do {
     /* read as much as we can */
     if (zstream.avail_in == 0) {
-      const size_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
+      const uint32_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
       const uint32_t offset = (compressed_length - remaining_bytes);
       // Make sure to read at offset to ensure concurrent access to the fd.
       if (!reader.ReadAtOffset(read_buf.data(), read_size, offset)) {
-        ALOGW("Zip: inflate read failed, getSize = %zu: %s", read_size, strerror(errno));
+        ALOGW("Zip: inflate read failed, getSize = %u: %s", read_size, strerror(errno));
         return kIoError;
       }
 
@@ -1018,7 +1019,8 @@
       if (!writer->Append(&write_buf[0], write_size)) {
         return kIoError;
       } else if (compute_crc) {
-        crc = crc32(crc, &write_buf[0], write_size);
+        DCHECK_LE(write_size, kBufSize);
+        crc = crc32(crc, &write_buf[0], static_cast<uint32_t>(write_size));
       }
 
       zstream.next_out = &write_buf[0];
@@ -1063,17 +1065,17 @@
 
   const uint32_t length = entry->uncompressed_length;
   uint32_t count = 0;
-  uint64_t crc = 0;
+  uLong crc = 0;
   while (count < length) {
     uint32_t remaining = length - count;
     off64_t offset = entry->offset + count;
 
     // Safe conversion because kBufSize is narrow enough for a 32 bit signed value.
-    const size_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
+    const uint32_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
 
     // Make sure to read at offset to ensure concurrent access to the fd.
     if (!mapped_zip.ReadAtOffset(buf.data(), block_size, offset)) {
-      ALOGW("CopyFileToFile: copy read failed, block_size = %zu, offset = %" PRId64 ": %s",
+      ALOGW("CopyFileToFile: copy read failed, block_size = %u, offset = %" PRId64 ": %s",
             block_size, static_cast<int64_t>(offset), strerror(errno));
       return kIoError;
     }
diff --git a/libziparchive/zip_archive_stream_entry.cc b/libziparchive/zip_archive_stream_entry.cc
index 9ec89b1..1ec95b6 100644
--- a/libziparchive/zip_archive_stream_entry.cc
+++ b/libziparchive/zip_archive_stream_entry.cc
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/logging.h>
 #include <log/log.h>
 
 #include <ziparchive/zip_archive.h>
@@ -77,6 +78,12 @@
 }
 
 const std::vector<uint8_t>* ZipArchiveStreamEntryUncompressed::Read() {
+  // Simple sanity check. The vector should *only* be handled by this code. A caller
+  // should not const-cast and modify the capacity. This may invalidate next_out.
+  //
+  // Note: it would be better to store the results of data() across Read calls.
+  CHECK_EQ(data_.capacity(), kBufSize);
+
   if (length_ == 0) {
     return nullptr;
   }
@@ -97,7 +104,8 @@
   if (bytes < data_.size()) {
     data_.resize(bytes);
   }
-  computed_crc32_ = crc32(computed_crc32_, data_.data(), data_.size());
+  computed_crc32_ = static_cast<uint32_t>(
+      crc32(computed_crc32_, data_.data(), static_cast<uint32_t>(data_.size())));
   length_ -= bytes;
   offset_ += bytes;
   return &data_;
@@ -192,9 +200,15 @@
 }
 
 const std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() {
+  // Simple sanity check. The vector should *only* be handled by this code. A caller
+  // should not const-cast and modify the capacity. This may invalidate next_out.
+  //
+  // Note: it would be better to store the results of data() across Read calls.
+  CHECK_EQ(out_.capacity(), kBufSize);
+
   if (z_stream_.avail_out == 0) {
     z_stream_.next_out = out_.data();
-    z_stream_.avail_out = out_.size();
+    z_stream_.avail_out = static_cast<uint32_t>(out_.size());
     ;
   }
 
@@ -203,7 +217,9 @@
       if (compressed_length_ == 0) {
         return nullptr;
       }
-      size_t bytes = (compressed_length_ > in_.size()) ? in_.size() : compressed_length_;
+      DCHECK_LE(in_.size(), std::numeric_limits<uint32_t>::max());  // Should be buf size = 64k.
+      uint32_t bytes = (compressed_length_ > in_.size()) ? static_cast<uint32_t>(in_.size())
+                                                         : compressed_length_;
       ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
       errno = 0;
       if (!archive->mapped_zip.ReadAtOffset(in_.data(), bytes, offset_)) {
@@ -230,14 +246,16 @@
 
     if (z_stream_.avail_out == 0) {
       uncompressed_length_ -= out_.size();
-      computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size());
+      computed_crc32_ = static_cast<uint32_t>(
+          crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
       return &out_;
     }
     if (zerr == Z_STREAM_END) {
       if (z_stream_.avail_out != 0) {
         // Resize the vector down to the actual size of the data.
         out_.resize(out_.size() - z_stream_.avail_out);
-        computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size());
+        computed_crc32_ = static_cast<uint32_t>(
+            crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
         uncompressed_length_ -= out_.size();
         return &out_;
       }
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index cea42d4..e471d5e 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/logging.h>
 #include <android-base/mapped_file.h>
 #include <android-base/unique_fd.h>
 #include <gtest/gtest.h>
@@ -65,7 +66,8 @@
 
 static void SetZipString(ZipString* zip_str, const std::string& str) {
   zip_str->name = reinterpret_cast<const uint8_t*>(str.c_str());
-  zip_str->name_length = str.size();
+  CHECK_LE(str.size(), std::numeric_limits<uint16_t>::max());
+  zip_str->name_length = static_cast<uint16_t>(str.size());
 }
 
 TEST(ziparchive, Open) {
@@ -332,7 +334,7 @@
 
   // Extract the entry to memory.
   std::vector<uint8_t> buffer(kAbUncompressedSize);
-  ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size()));
+  ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], static_cast<uint32_t>(buffer.size())));
 
   // Extract the entry to a file.
   TemporaryFile tmp_output_file;
@@ -415,7 +417,8 @@
   ASSERT_EQ(0, fstat(fd, &sb));
 
   // Memory map the file first and open the archive from the memory region.
-  auto file_map{android::base::MappedFile::FromFd(fd, 0, sb.st_size, PROT_READ)};
+  auto file_map{
+      android::base::MappedFile::FromFd(fd, 0, static_cast<size_t>(sb.st_size), PROT_READ)};
   ZipArchiveHandle handle;
   ASSERT_EQ(0,
             OpenArchiveFromMemory(file_map->data(), file_map->size(), zip_path.c_str(), &handle));
@@ -488,7 +491,8 @@
 
   std::vector<uint8_t> cmp_data(entry.uncompressed_length);
   ASSERT_EQ(entry.uncompressed_length, read_data.size());
-  ASSERT_EQ(0, ExtractToMemory(handle, &entry, cmp_data.data(), cmp_data.size()));
+  ASSERT_EQ(
+      0, ExtractToMemory(handle, &entry, cmp_data.data(), static_cast<uint32_t>(cmp_data.size())));
   ASSERT_TRUE(memcmp(read_data.data(), cmp_data.data(), read_data.size()) == 0);
 
   CloseArchive(handle);
@@ -737,8 +741,8 @@
 };
 
 TEST(ziparchive, Inflate) {
-  const uint32_t compressed_length = kATxtContentsCompressed.size();
-  const uint32_t uncompressed_length = kATxtContents.size();
+  const uint32_t compressed_length = static_cast<uint32_t>(kATxtContentsCompressed.size());
+  const uint32_t uncompressed_length = static_cast<uint32_t>(kATxtContents.size());
 
   const VectorReader reader(kATxtContentsCompressed);
   {
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index 0df0fa5..ae9d145 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -169,8 +169,8 @@
     year = 80;
   }
 
-  *out_date = (year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday;
-  *out_time = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
+  *out_date = static_cast<uint16_t>((year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday);
+  *out_time = static_cast<uint16_t>(ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1);
 }
 
 static void CopyFromFileEntry(const ZipWriter::FileEntry& src, bool use_data_descriptor,
@@ -193,7 +193,8 @@
   dst->compression_method = src.compression_method;
   dst->last_mod_time = src.last_mod_time;
   dst->last_mod_date = src.last_mod_date;
-  dst->file_name_length = src.path.size();
+  DCHECK_LE(src.path.size(), std::numeric_limits<uint16_t>::max());
+  dst->file_name_length = static_cast<uint16_t>(src.path.size());
   dst->extra_field_length = src.padding_length;
 }
 
@@ -203,6 +204,11 @@
     return kInvalidState;
   }
 
+  // Can only have 16535 entries because of zip records.
+  if (files_.size() == std::numeric_limits<uint16_t>::max()) {
+    return HandleError(kIoError);
+  }
+
   if (flags & kAlign32) {
     return kInvalidAlign32Flag;
   }
@@ -210,10 +216,17 @@
   if (powerof2(alignment) == 0) {
     return kInvalidAlignment;
   }
+  if (alignment > std::numeric_limits<uint16_t>::max()) {
+    return kInvalidAlignment;
+  }
 
   FileEntry file_entry = {};
   file_entry.local_file_header_offset = current_offset_;
   file_entry.path = path;
+  // No support for larger than 4GB files.
+  if (file_entry.local_file_header_offset > std::numeric_limits<uint32_t>::max()) {
+    return HandleError(kIoError);
+  }
 
   if (!IsValidEntryName(reinterpret_cast<const uint8_t*>(file_entry.path.data()),
                         file_entry.path.size())) {
@@ -237,7 +250,7 @@
   std::vector<char> zero_padding;
   if (alignment != 0 && (offset & (alignment - 1))) {
     // Pad the extra field so the data will be aligned.
-    uint16_t padding = alignment - (offset % alignment);
+    uint16_t padding = static_cast<uint16_t>(alignment - (offset % alignment));
     file_entry.padding_length = padding;
     offset += padding;
     zero_padding.resize(padding, 0);
@@ -314,7 +327,8 @@
   }
 
   z_stream_->next_out = buffer_.data();
-  z_stream_->avail_out = buffer_.size();
+  DCHECK_EQ(buffer_.size(), kBufSize);
+  z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
   return kNoError;
 }
 
@@ -322,25 +336,31 @@
   if (state_ != State::kWritingEntry) {
     return HandleError(kInvalidState);
   }
+  // Need to be able to mark down data correctly.
+  if (len + static_cast<uint64_t>(current_file_entry_.uncompressed_size) >
+      std::numeric_limits<uint32_t>::max()) {
+    return HandleError(kIoError);
+  }
+  uint32_t len32 = static_cast<uint32_t>(len);
 
   int32_t result = kNoError;
   if (current_file_entry_.compression_method & kCompressDeflated) {
-    result = CompressBytes(&current_file_entry_, data, len);
+    result = CompressBytes(&current_file_entry_, data, len32);
   } else {
-    result = StoreBytes(&current_file_entry_, data, len);
+    result = StoreBytes(&current_file_entry_, data, len32);
   }
 
   if (result != kNoError) {
     return result;
   }
 
-  current_file_entry_.crc32 =
-      crc32(current_file_entry_.crc32, reinterpret_cast<const Bytef*>(data), len);
-  current_file_entry_.uncompressed_size += len;
+  current_file_entry_.crc32 = static_cast<uint32_t>(
+      crc32(current_file_entry_.crc32, reinterpret_cast<const Bytef*>(data), len32));
+  current_file_entry_.uncompressed_size += len32;
   return kNoError;
 }
 
-int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, size_t len) {
+int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, uint32_t len) {
   CHECK(state_ == State::kWritingEntry);
 
   if (fwrite(data, 1, len, file_) != len) {
@@ -351,7 +371,7 @@
   return kNoError;
 }
 
-int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, size_t len) {
+int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, uint32_t len) {
   CHECK(state_ == State::kWritingEntry);
   CHECK(z_stream_);
   CHECK(z_stream_->next_out != nullptr);
@@ -379,7 +399,8 @@
 
       // Reset the output buffer for the next input.
       z_stream_->next_out = buffer_.data();
-      z_stream_->avail_out = buffer_.size();
+      DCHECK_EQ(buffer_.size(), kBufSize);
+      z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
     }
   }
   return kNoError;
@@ -404,7 +425,8 @@
     current_offset_ += write_bytes;
 
     z_stream_->next_out = buffer_.data();
-    z_stream_->avail_out = buffer_.size();
+    DCHECK_EQ(buffer_.size(), kBufSize);
+    z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
   }
   if (zerr != Z_STREAM_END) {
     return HandleError(kZlibError);
@@ -491,7 +513,11 @@
     cdr.crc32 = file.crc32;
     cdr.compressed_size = file.compressed_size;
     cdr.uncompressed_size = file.uncompressed_size;
-    cdr.file_name_length = file.path.size();
+    // Checked in IsValidEntryName.
+    DCHECK_LE(file.path.size(), std::numeric_limits<uint16_t>::max());
+    cdr.file_name_length = static_cast<uint16_t>(file.path.size());
+    // Checked in StartAlignedEntryWithTime.
+    DCHECK_LE(file.local_file_header_offset, std::numeric_limits<uint32_t>::max());
     cdr.local_file_header_offset = static_cast<uint32_t>(file.local_file_header_offset);
     if (fwrite(&cdr, sizeof(cdr), 1, file_) != 1) {
       return HandleError(kIoError);
@@ -508,10 +534,15 @@
   er.eocd_signature = EocdRecord::kSignature;
   er.disk_num = 0;
   er.cd_start_disk = 0;
-  er.num_records_on_disk = files_.size();
-  er.num_records = files_.size();
-  er.cd_size = current_offset_ - startOfCdr;
-  er.cd_start_offset = startOfCdr;
+  // Checked when adding entries.
+  DCHECK_LE(files_.size(), std::numeric_limits<uint16_t>::max());
+  er.num_records_on_disk = static_cast<uint16_t>(files_.size());
+  er.num_records = static_cast<uint16_t>(files_.size());
+  if (current_offset_ > std::numeric_limits<uint32_t>::max()) {
+    return HandleError(kIoError);
+  }
+  er.cd_size = static_cast<uint32_t>(current_offset_ - startOfCdr);
+  er.cd_start_offset = static_cast<uint32_t>(startOfCdr);
 
   if (fwrite(&er, sizeof(er), 1, file_) != 1) {
     return HandleError(kIoError);
diff --git a/libziparchive/zip_writer_test.cc b/libziparchive/zip_writer_test.cc
index 7322afb..63adbbc 100644
--- a/libziparchive/zip_writer_test.cc
+++ b/libziparchive/zip_writer_test.cc
@@ -279,7 +279,8 @@
 
   std::vector<uint8_t> decompress(kBufSize);
   memset(decompress.data(), 0, kBufSize);
-  ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(), decompress.size()));
+  ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(),
+                               static_cast<uint32_t>(decompress.size())));
   EXPECT_EQ(0, memcmp(decompress.data(), buffer.data(), kBufSize))
       << "Input buffer and output buffer are different.";
 
@@ -391,7 +392,7 @@
   actual.resize(expected.size());
 
   uint8_t* buffer = reinterpret_cast<uint8_t*>(&*actual.begin());
-  if (ExtractToMemory(handle, zip_entry, buffer, actual.size()) != 0) {
+  if (ExtractToMemory(handle, zip_entry, buffer, static_cast<uint32_t>(actual.size())) != 0) {
     return ::testing::AssertionFailure() << "failed to extract entry";
   }