summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/linker/image_writer.cc12
-rw-r--r--runtime/image.cc29
-rw-r--r--runtime/image.h8
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_