Check for overflow before allocating memory fore decompression.

On 32bit devices, an ZipEntry64 may have size > 2^32, we should check
for such cases before attempting to allocate memory.

Test: mm -j
Change-Id: I0f916ef4b2a692f167719a74bd6ff2e887c6c2ce
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index d0cb687..376c511 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -712,8 +712,14 @@
     // Add the end of zip file (mainly central directory) as a normal chunk.
     size_t entries_end = 0;
     if (!temp_entries.empty()) {
-      entries_end = static_cast<size_t>(temp_entries.back().second.offset +
-                                        temp_entries.back().second.compressed_length);
+      CHECK_GE(temp_entries.back().second.offset, 0);
+      if (__builtin_add_overflow(temp_entries.back().second.offset,
+                                 temp_entries.back().second.compressed_length, &entries_end)) {
+        LOG(ERROR) << "`entries_end` overflows on entry with offset "
+                   << temp_entries.back().second.offset << " and compressed_length "
+                   << temp_entries.back().second.compressed_length;
+        return false;
+      }
     }
     CHECK_LT(entries_end, file_content_.size());
     chunks_.emplace_back(CHUNK_NORMAL, entries_end, &file_content_,
@@ -735,8 +741,16 @@
         LOG(ERROR) << "Failed to add " << entry_name << " to target chunks";
         return false;
       }
-
-      pos += temp_entries[nextentry].second.compressed_length;
+      if (temp_entries[nextentry].second.compressed_length > std::numeric_limits<size_t>::max()) {
+        LOG(ERROR) << "Entry " << name << " compressed size exceeds size of address space. "
+                   << entry.compressed_length;
+        return false;
+      }
+      if (__builtin_add_overflow(pos, temp_entries[nextentry].second.compressed_length, &pos)) {
+        LOG(ERROR) << "`pos` overflows after adding "
+                   << temp_entries[nextentry].second.compressed_length;
+        return false;
+      }
       ++nextentry;
       continue;
     }
@@ -758,6 +772,12 @@
 
 bool ZipModeImage::AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name,
                                        ZipEntry64* entry) {
+  if (entry->compressed_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to add " << entry_name
+               << " because's compressed size exceeds size of address space. "
+               << entry->compressed_length;
+    return false;
+  }
   size_t compressed_len = entry->compressed_length;
   if (compressed_len == 0) return true;
 
@@ -775,6 +795,12 @@
     }
   } else if (entry->method == kCompressDeflated) {
     size_t uncompressed_len = entry->uncompressed_length;
+    if (uncompressed_len > std::numeric_limits<size_t>::max()) {
+      LOG(ERROR) << "Failed to add " << entry_name
+                 << " because's compressed size exceeds size of address space. "
+                 << uncompressed_len;
+      return false;
+    }
     std::vector<uint8_t> uncompressed_data(uncompressed_len);
     int ret = ExtractToMemory(handle, entry, uncompressed_data.data(), uncompressed_len);
     if (ret != 0) {
diff --git a/install/install.cpp b/install/install.cpp
index 7533732..1b220cb 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -246,7 +246,13 @@
     LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD_PROPERTIES;
     return false;
   }
-  uint32_t properties_entry_length = properties_entry.uncompressed_length;
+  auto properties_entry_length = properties_entry.uncompressed_length;
+  if (properties_entry_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to extract " << AB_OTA_PAYLOAD_PROPERTIES
+               << " because's uncompressed size exceeds size of address space. "
+               << properties_entry_length;
+    return false;
+  }
   std::vector<uint8_t> payload_properties(properties_entry_length);
   int32_t err =
       ExtractToMemory(zip, &properties_entry, payload_properties.data(), properties_entry_length);
diff --git a/install/verifier.cpp b/install/verifier.cpp
index d8bc53f..3f02601 100644
--- a/install/verifier.cpp
+++ b/install/verifier.cpp
@@ -323,6 +323,12 @@
   std::string_view name;
   ZipEntry64 entry;
   while ((iter_status = Next(cookie, &entry, &name)) == 0) {
+    if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+      LOG(ERROR) << "Failed to extract " << name
+                 << " because's uncompressed size exceeds size of address space. "
+                 << entry.uncompressed_length;
+      return {};
+    }
     std::vector<uint8_t> pem_content(entry.uncompressed_length);
     if (int32_t extract_status =
             ExtractToMemory(handle, &entry, pem_content.data(), pem_content.size());
diff --git a/install/wipe_device.cpp b/install/wipe_device.cpp
index 0f896c4..915c87b 100644
--- a/install/wipe_device.cpp
+++ b/install/wipe_device.cpp
@@ -51,7 +51,12 @@
   std::string partition_list_content;
   ZipEntry64 entry;
   if (FindEntry(zip, RECOVERY_WIPE_ENTRY_NAME, &entry) == 0) {
-    uint32_t length = entry.uncompressed_length;
+    auto length = entry.uncompressed_length;
+    if (length > std::numeric_limits<size_t>::max()) {
+      LOG(ERROR) << "Failed to extract " << RECOVERY_WIPE_ENTRY_NAME
+                 << " because's uncompressed size exceeds size of address space. " << length;
+      return {};
+    }
     partition_list_content = std::string(length, '\0');
     if (auto err = ExtractToMemory(
             zip, &entry, reinterpret_cast<uint8_t*>(partition_list_content.data()), length);
diff --git a/updater/install.cpp b/updater/install.cpp
index cfa4d9d..2959650 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h>
 #include <utime.h>
 
+#include <limits>
 #include <memory>
 #include <string>
 #include <vector>
@@ -172,6 +173,11 @@
     }
 
     std::string buffer;
+    if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+      return ErrorAbort(state, kPackageExtractFileFailure,
+                        "%s(): Entry `%s` Uncompressed size exceeds size of address space.", name,
+                        zip_path.c_str());
+    }
     buffer.resize(entry.uncompressed_length);
 
     int32_t ret =
diff --git a/updater/target_files.cpp b/updater/target_files.cpp
index 9519232..207146f 100644
--- a/updater/target_files.cpp
+++ b/updater/target_files.cpp
@@ -137,6 +137,13 @@
     return true;
   }
 
+  if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to extract " << name
+               << " because's uncompressed size exceeds size of address space. "
+               << entry.uncompressed_length;
+    return false;
+  }
+
   content->resize(entry.uncompressed_length);
   if (auto extract_err = ExtractToMemory(
           handle_, &entry, reinterpret_cast<uint8_t*>(&content->at(0)), entry.uncompressed_length);
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 73ca0e5..c526734 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -170,7 +170,12 @@
                << " in the package: " << ErrorCodeString(find_err);
     return false;
   }
-
+  if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to extract " << entry_name
+               << " because's uncompressed size exceeds size of address space. "
+               << entry.uncompressed_length;
+    return false;
+  }
   content->resize(entry.uncompressed_length);
   int extract_err = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&content->at(0)),
                                     entry.uncompressed_length);