From: Jeff Hao Date: Mon, 6 Mar 2017 23:05:38 +0000 (-0800) Subject: Fix dexlayout calculation of code item size. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a64a64cfae5c6dd7c2bdb039a92e9313dfd1e315;p=android-x86%2Fart.git Fix dexlayout calculation of code item size. Calculation of code item size was based on looking for the latest catch handler referenced by a try block, but there can be handlers that aren't referenced by any try blocks. This fix manually reads all handlers to ensure the end is actually reached. Bug: 35978524 Test: mm test-art-host-gtest-dexlayout_test Change-Id: I33b30087845f806cd34b888f1ec457ee692f2af4 --- diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index a69409947..34983cf5f 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -64,23 +64,18 @@ static uint32_t GetCodeItemSize(const DexFile& dex_file, const DexFile::CodeItem uintptr_t insns_end = reinterpret_cast(&disk_code_item.insns_[insns_size]); return insns_end - code_item_start; } else { - uint32_t last_handler_off = 0; - for (uint32_t i = 0; i < tries_size; ++i) { - // Iterate over the try items to find the last catch handler. - const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i); - uint16_t handler_off = disk_try_item->handler_off_; - if (handler_off > last_handler_off) { - last_handler_off = handler_off; + // Get the start of the handler data. + const uint8_t* handler_data = DexFile::GetCatchHandlerData(disk_code_item, 0); + uint32_t handlers_size = DecodeUnsignedLeb128(&handler_data); + // Manually read each handler. + for (uint32_t i = 0; i < handlers_size; ++i) { + int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2; + if (uleb128_count <= 0) { + uleb128_count = -uleb128_count + 1; + } + for (int32_t j = 0; j < uleb128_count; ++j) { + DecodeUnsignedLeb128(&handler_data); } - } - // Decode the final handler to see where it ends. - const uint8_t* handler_data = DexFile::GetCatchHandlerData(disk_code_item, last_handler_off); - int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2; - if (uleb128_count <= 0) { - uleb128_count = -uleb128_count + 1; - } - for (int32_t i = 0; i < uleb128_count; ++i) { - DecodeUnsignedLeb128(&handler_data); } return reinterpret_cast(handler_data) - code_item_start; } diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index 952909c1e..bd6548e65 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -95,6 +95,29 @@ static const char kUnreferenced0SizeCatchHandlerInputDex[] = "AAABIAAAAgAAADwBAAABEAAAAgAAANwBAAACIAAAEQAAAOoBAAADIAAAAgAAAKYCAAAAIAAAAQAA" "ALkCAAAAEAAAAQAAAMgCAAA="; +// Dex file with an unreferenced catch handler at end of code item. +// Constructed by building a dex file with try/catch blocks and hex editing. +static const char kUnreferencedEndingCatchHandlerInputDex[] = + "ZGV4CjAzNQCEflufI6xGTDDRmLpbfYi6ujPrDLIwvYcEBAAAcAAAAHhWNBIAAAAAAAAAAGQDAAAT" + "AAAAcAAAAAgAAAC8AAAAAwAAANwAAAABAAAAAAEAAAUAAAAIAQAAAQAAADABAAC0AgAAUAEAAE4C" + "AABWAgAAXgIAAGYCAAB4AgAAhwIAAJ4CAAC1AgAAyQIAAN0CAADxAgAA9wIAAP0CAAAAAwAABAMA" + "ABkDAAAcAwAAIgMAACcDAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAMAAAADgAAAAwAAAAGAAAA" + "AAAAAA0AAAAGAAAAQAIAAA0AAAAGAAAASAIAAAUAAQARAAAAAAAAAAAAAAAAAAAADwAAAAAAAgAQ" + "AAAAAQABABIAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAADAAAAAAAAAFADAAAAAAAAAQABAAEA" + "AAAwAwAABAAAAHAQBAAAAA4AAgAAAAIAAgA1AwAAIQAAAGIAAAAaAQoAbiADABAAYgAAABoBCwBu" + "IAMAEAAOAA0AYgAAABoBAQBuIAMAEAAo8A0AYgAAABoBAgBuIAMAEAAo7gAAAAAAAAcAAQAHAAAA" + "BwABAAIBAg8BAhgAAwABAAIAAgBCAwAAIQAAAGIAAAAaAQoAbiADABAAYgAAABoBCwBuIAMAEAAO" + "AA0AYgAAABoBAQBuIAMAEAAo8A0AYgAAABoBAgBuIAMAEAAo7gAAAAAAAAcAAQAHAAAABwABAAIB" + "Ag8BAhgAAQAAAAQAAAABAAAABwAGPGluaXQ+AAZDYXRjaDEABkNhdGNoMgAQSGFuZGxlclRlc3Qu" + "amF2YQANTEhhbmRsZXJUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4" + "Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9s" + "YW5nL1N5c3RlbTsABFRyeTEABFRyeTIAAVYAAlZMABNbTGphdmEvbGFuZy9TdHJpbmc7AAFhAARt" + "YWluAANvdXQAB3ByaW50bG4AAQAHDgAEAAcOfHsCeB0eih4AEQEABw59ewJ3HR6LHgAAAAMAAIGA" + "BNACAQnoAgEJ1AMAAA0AAAAAAAAAAQAAAAAAAAABAAAAEwAAAHAAAAACAAAACAAAALwAAAADAAAA" + "AwAAANwAAAAEAAAAAQAAAAABAAAFAAAABQAAAAgBAAAGAAAAAQAAADABAAABIAAAAwAAAFABAAAB" + "EAAAAgAAAEACAAACIAAAEwAAAE4CAAADIAAAAwAAADADAAAAIAAAAQAAAFADAAAAEAAAAQAAAGQD" + "AAA="; + // Dex file with multiple code items that have the same debug_info_off_. Constructed by a modified // dexlayout on XandY. static const char kDexFileDuplicateOffset[] = @@ -390,6 +413,14 @@ TEST_F(DexLayoutTest, Unreferenced0SizeCatchHandler) { kUnreferenced0SizeCatchHandlerInputDex)) << error_msg; } +TEST_F(DexLayoutTest, UnreferencedEndingCatchHandler) { + // Disable test on target. + TEST_DISABLED_FOR_TARGET(); + std::string error_msg; + ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg, + kUnreferencedEndingCatchHandlerInputDex)) << error_msg; +} + TEST_F(DexLayoutTest, DuplicateOffset) { ScratchFile temp; WriteBase64ToFile(kDexFileDuplicateOffset, temp.GetFile());