diff options
| -rw-r--r-- | dex2oat/linker/image_writer.cc | 12 | ||||
| -rw-r--r-- | runtime/image.cc | 29 | ||||
| -rw-r--r-- | runtime/image.h | 8 |
3 files changed, 45 insertions, 4 deletions
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index ae6feeca1f..07afa369aa 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -155,11 +155,19 @@ static ArrayRef<const uint8_t> MaybeCompressData(ArrayRef<const uint8_t> source, << PrettyDuration(NanoTime() - compress_start_time); if (kIsDebugBuild) { dchecked_vector<uint8_t> decompressed(source.size()); - const size_t decompressed_size = LZ4_decompress_safe( + size_t decompressed_size; + std::string error_msg; + bool ok = LZ4_decompress_safe_checked( reinterpret_cast<char*>(storage->data()), reinterpret_cast<char*>(decompressed.data()), storage->size(), - decompressed.size()); + decompressed.size(), + &decompressed_size, + &error_msg); + if (!ok) { + LOG(FATAL) << error_msg; + UNREACHABLE(); + } CHECK_EQ(decompressed_size, decompressed.size()); CHECK_EQ(memcmp(source.data(), decompressed.data(), source.size()), 0) << image_storage_mode; } diff --git a/runtime/image.cc b/runtime/image.cc index b39ffe5690..b8536db1fe 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -19,6 +19,8 @@ #include <lz4.h> #include <sstream> +#include "android-base/stringprintf.h" + #include "base/bit_utils.h" #include "base/length_prefixed_array.h" #include "base/utils.h" @@ -170,6 +172,23 @@ PointerSize ImageHeader::GetPointerSize() const { return ConvertToPointerSize(pointer_size_); } +bool LZ4_decompress_safe_checked(const char* source, + char* dest, + int compressed_size, + int max_decompressed_size, + /*out*/ size_t* decompressed_size_checked, + /*out*/ std::string* error_msg) { + int decompressed_size = LZ4_decompress_safe(source, dest, compressed_size, max_decompressed_size); + if (UNLIKELY(decompressed_size < 0)) { + *error_msg = android::base::StringPrintf("LZ4_decompress_safe() returned negative size: %d", + decompressed_size); + return false; + } else { + *decompressed_size_checked = static_cast<size_t>(decompressed_size); + return true; + } +} + bool ImageHeader::Block::Decompress(uint8_t* out_ptr, const uint8_t* in_ptr, std::string* error_msg) const { @@ -182,11 +201,17 @@ bool ImageHeader::Block::Decompress(uint8_t* out_ptr, case kStorageModeLZ4: case kStorageModeLZ4HC: { // LZ4HC and LZ4 have same internal format, both use LZ4_decompress. - const size_t decompressed_size = LZ4_decompress_safe( + size_t decompressed_size; + bool ok = LZ4_decompress_safe_checked( reinterpret_cast<const char*>(in_ptr) + data_offset_, reinterpret_cast<char*>(out_ptr) + image_offset_, data_size_, - image_size_); + image_size_, + &decompressed_size, + error_msg); + if (!ok) { + return false; + } CHECK_EQ(decompressed_size, image_size_); break; } diff --git a/runtime/image.h b/runtime/image.h index 8f045e9339..bc0c9dd348 100644 --- a/runtime/image.h +++ b/runtime/image.h @@ -520,6 +520,14 @@ std::ostream& operator<<(std::ostream& os, ImageHeader::StorageMode mode); std::ostream& operator<<(std::ostream& os, const ImageSection& section); +// Wrapper over LZ4_decompress_safe() that checks if return value is negative. See b/242914915. +bool LZ4_decompress_safe_checked(const char* source, + char* dest, + int compressed_size, + int max_decompressed_size, + /*out*/ size_t* decompressed_size_checked, + /*out*/ std::string* error_msg); + } // namespace art #endif // ART_RUNTIME_IMAGE_H_ |