OSDN Git Service

Fix dexlayout calculation of code item size.
authorJeff Hao <jeffhao@google.com>
Mon, 6 Mar 2017 23:05:38 +0000 (15:05 -0800)
committerJeff Hao <jeffhao@google.com>
Tue, 7 Mar 2017 00:24:05 +0000 (16:24 -0800)
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

dexlayout/dex_ir.cc
dexlayout/dexlayout_test.cc

index a694099..34983cf 100644 (file)
@@ -64,23 +64,18 @@ static uint32_t GetCodeItemSize(const DexFile& dex_file, const DexFile::CodeItem
     uintptr_t insns_end = reinterpret_cast<uintptr_t>(&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<uintptr_t>(handler_data) - code_item_start;
   }
index 952909c..bd6548e 100644 (file)
@@ -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());