diff options
Diffstat (limited to 'applypatch')
-rw-r--r-- | applypatch/Android.bp | 30 | ||||
-rw-r--r-- | applypatch/imgdiff.cpp | 59 | ||||
-rw-r--r-- | applypatch/include/applypatch/imgdiff_image.h | 7 |
3 files changed, 70 insertions, 26 deletions
diff --git a/applypatch/Android.bp b/applypatch/Android.bp index 13a962584..0d6d23b90 100644 --- a/applypatch/Android.bp +++ b/applypatch/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["bootable_recovery_applypatch_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "bootable_recovery_applypatch_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "applypatch_defaults", @@ -54,7 +71,7 @@ cc_library_static { "libbz", "libedify", "libotautil", - "libz", + "libz_stable", ], shared_libs: [ @@ -120,7 +137,7 @@ cc_binary { "libbase", "libcrypto", "liblog", - "libz", + "libz_stable", "libziparchive", ], @@ -129,9 +146,9 @@ cc_binary { ], } -cc_library_host_static { +cc_library_static { name: "libimgdiff", - + host_supported: true, defaults: [ "applypatch_defaults", ], @@ -152,14 +169,13 @@ cc_library_host_static { "liblog", "libotautil", "libutils", - "libz", + "libz_stable", "libziparchive", ], } cc_binary_host { name: "imgdiff", - srcs: [ "imgdiff_main.cpp", ], @@ -180,6 +196,6 @@ cc_binary_host { "liblog", "libbrotli", "libbz", - "libz", + "libz_stable", ], } diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp index 6ad4a6105..376c511c2 100644 --- a/applypatch/imgdiff.cpp +++ b/applypatch/imgdiff.cpp @@ -682,9 +682,9 @@ bool ZipModeImage::InitializeChunks(const std::string& filename, ZipArchiveHandl } // Create a list of deflated zip entries, sorted by offset. - std::vector<std::pair<std::string, ZipEntry>> temp_entries; + std::vector<std::pair<std::string, ZipEntry64>> temp_entries; std::string name; - ZipEntry entry; + ZipEntry64 entry; while ((ret = Next(cookie, &entry, &name)) == 0) { if (entry.method == kCompressDeflated || limit_ > 0) { temp_entries.emplace_back(name, entry); @@ -712,8 +712,14 @@ bool ZipModeImage::InitializeChunks(const std::string& filename, ZipArchiveHandl // 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 @@ bool ZipModeImage::InitializeChunks(const std::string& filename, ZipArchiveHandl 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; } @@ -757,7 +771,13 @@ bool ZipModeImage::InitializeChunks(const std::string& filename, ZipArchiveHandl } bool ZipModeImage::AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name, - ZipEntry* entry) { + 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 @@ bool ZipModeImage::AddZipEntryToChunks(ZipArchiveHandle handle, const std::strin } } 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) { @@ -965,7 +991,7 @@ bool ZipModeImage::SplitZipModeImageWithLimit(const ZipModeImage& tgt_image, used_src_ranges.Insert(src_ranges); split_src_ranges->push_back(std::move(src_ranges)); } - src_ranges.Clear(); + src_ranges = {}; // We don't have enough space for the current chunk; start a new split image and handle // this chunk there. @@ -1035,23 +1061,24 @@ bool ZipModeImage::AddSplitImageFromChunkList(const ZipModeImage& tgt_image, } ZipModeImage split_tgt_image(false); - split_tgt_image.Initialize(std::move(aligned_tgt_chunks), {}); + split_tgt_image.Initialize(aligned_tgt_chunks, {}); split_tgt_image.MergeAdjacentNormalChunks(); - // Construct the dummy source file based on the src_ranges. - std::vector<uint8_t> src_content; + // Construct the split source file based on the split src ranges. + std::vector<uint8_t> split_src_content; for (const auto& r : split_src_ranges) { size_t end = std::min(src_image.file_content_.size(), r.second * BLOCK_SIZE); - src_content.insert(src_content.end(), src_image.file_content_.begin() + r.first * BLOCK_SIZE, - src_image.file_content_.begin() + end); + split_src_content.insert(split_src_content.end(), + src_image.file_content_.begin() + r.first * BLOCK_SIZE, + src_image.file_content_.begin() + end); } // We should not have an empty src in our design; otherwise we will encounter an error in - // bsdiff since src_content.data() == nullptr. - CHECK(!src_content.empty()); + // bsdiff since split_src_content.data() == nullptr. + CHECK(!split_src_content.empty()); ZipModeImage split_src_image(true); - split_src_image.Initialize(split_src_chunks, std::move(src_content)); + split_src_image.Initialize(split_src_chunks, split_src_content); split_tgt_images->push_back(std::move(split_tgt_image)); split_src_images->push_back(std::move(split_src_image)); diff --git a/applypatch/include/applypatch/imgdiff_image.h b/applypatch/include/applypatch/imgdiff_image.h index 671605160..b579e56ae 100644 --- a/applypatch/include/applypatch/imgdiff_image.h +++ b/applypatch/include/applypatch/imgdiff_image.h @@ -211,7 +211,7 @@ class ZipModeImage : public Image { bool Initialize(const std::string& filename) override; - // Initialize a dummy ZipModeImage from an existing ImageChunk vector. For src img pieces, we + // Initialize a fake ZipModeImage from an existing ImageChunk vector. For src img pieces, we // reconstruct a new file_content based on the source ranges; but it's not needed for the tgt img // pieces; because for each chunk both the data and their offset within the file are unchanged. void Initialize(const std::vector<ImageChunk>& chunks, const std::vector<uint8_t>& file_content) { @@ -257,7 +257,8 @@ class ZipModeImage : public Image { // Initialize image chunks based on the zip entries. bool InitializeChunks(const std::string& filename, ZipArchiveHandle handle); // Add the a zip entry to the list. - bool AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name, ZipEntry* entry); + bool AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name, + ZipEntry64* entry); // Return the real size of the zip file. (omit the trailing zeros that used for alignment) bool GetZipFileSize(size_t* input_file_size); @@ -265,7 +266,7 @@ class ZipModeImage : public Image { const std::vector<ZipModeImage>& split_src_images, std::vector<SortedRangeSet>& split_src_ranges, size_t total_tgt_size); - // Construct the dummy split images based on the chunks info and source ranges; and move them into + // Construct the fake split images based on the chunks info and source ranges; and move them into // the given vectors. Return true if we add a new split image into |split_tgt_images|, and // false otherwise. static bool AddSplitImageFromChunkList(const ZipModeImage& tgt_image, |