Home | History | Annotate | Download | only in art
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package art;
     18 
     19 import java.lang.reflect.*;
     20 import java.util.Base64;
     21 import java.nio.ByteBuffer;
     22 
     23 public class Test1949 {
     24   private final static boolean isDalvik = System.getProperty("java.vm.name").equals("Dalvik");
     25 
     26   // This dex file is specifically crafted to have exactly 4 methodIDs in it. They are (in order):
     27   //   (0) Ljava/lang/Object;-><init>()V
     28   //   (1) Lxyz/Transform;-><init>()V
     29   //   (2) Lxyz/Transform;->bar()V
     30   //   (3) Lxyz/Transform;->foo()V
     31   //
     32   // In the transformed version of the dex file there is a new method. The new list of methodIDs is:
     33   //   (0) Lart/Test1949;->doNothing()V
     34   //   (1) Ljava/lang/Object;-><init>()V
     35   //   (2) Lxyz/Transform;-><init>()V
     36   //   (3) Lxyz/Transform;->bar()V
     37   //   (4) Lxyz/Transform;->foo()V
     38   //
     39   // This test tries to get the JIT to read out-of-bounds on the initial dex file by getting it to
     40   // read the 5th method id of the new file (Lxyz/Transform;->foo()V) from the old dex file (which
     41   // only has 4 method ids).
     42   //
     43   // To do this we need to make sure that the class being transformed is near the end of the
     44   // alphabet (package xyz, method foo). If it is further forward than the other method-ids then the
     45   // JIT will read an incorrect (but valid) method-id from the old-dex file. This is why the error
     46   // wasn't caught in our other tests (package art is always at the front).
     47   //
     48   // The final method that causes the OOB read needs to be a native method because that is the only
     49   // method-type the jit uses dex-file information to keep track of.
     50 
     51   /**
     52    * base64 encoded class/dex file for
     53    * package xyz;
     54    * public class Transform {
     55    *   public native void foo();
     56    *   public void bar() {}
     57    * }
     58    */
     59   private static final byte[] CLASS_BYTES_INIT = Base64.getDecoder().decode(
     60     "yv66vgAAADUADwoAAwAMBwANBwAOAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJU" +
     61     "YWJsZQEAA2ZvbwEAA2JhcgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwABAAFAQANeHl6" +
     62     "L1RyYW5zZm9ybQEAEGphdmEvbGFuZy9PYmplY3QAIQACAAMAAAAAAAMAAQAEAAUAAQAGAAAAHQAB" +
     63     "AAEAAAAFKrcAAbEAAAABAAcAAAAGAAEAAAACAQEACAAFAAAAAQAJAAUAAQAGAAAAGQAAAAEAAAAB" +
     64     "sQAAAAEABwAAAAYAAQAAAAQAAQAKAAAAAgAL");
     65   private static final byte[] DEX_BYTES_INIT = Base64.getDecoder().decode(
     66     "ZGV4CjAzNQBDUutFJpeT+okk+aXah8NQ61q2XRtkmChwAgAAcAAAAHhWNBIAAAAAAAAAANwBAAAI" +
     67     "AAAAcAAAAAMAAACQAAAAAQAAAJwAAAAAAAAAAAAAAAQAAACoAAAAAQAAAMgAAACIAQAA6AAAABwB" +
     68     "AAAkAQAAOAEAAEkBAABZAQAAXAEAAGEBAABmAQAAAQAAAAIAAAAEAAAABAAAAAIAAAAAAAAAAAAA" +
     69     "AAAAAAABAAAAAAAAAAEAAAAFAAAAAQAAAAYAAAABAAAAAQAAAAAAAAAAAAAAAwAAAAAAAADDAQAA" +
     70     "AAAAAAEAAQABAAAAEgEAAAQAAABwEAAAAAAOAAEAAQAAAAAAFgEAAAEAAAAOAAIADgAEAA4AAAAG" +
     71     "PGluaXQ+ABJMamF2YS9sYW5nL09iamVjdDsAD0x4eXovVHJhbnNmb3JtOwAOVHJhbnNmb3JtLmph" +
     72     "dmEAAVYAA2JhcgADZm9vAFt+fkQ4eyJtaW4tYXBpIjoxLCJzaGEtMSI6IjkwZWYyMjkwNWMzZmVj" +
     73     "Y2FiMjMwMzBhNmJkYzU2NTcwYTMzNWVmMDUiLCJ2ZXJzaW9uIjoidjEuMS44LWRldiJ9AAAAAQIB" +
     74     "gYAE6AECAYACAYECAAAAAAAAAAAMAAAAAAAAAAEAAAAAAAAAAQAAAAgAAABwAAAAAgAAAAMAAACQ" +
     75     "AAAAAwAAAAEAAACcAAAABQAAAAQAAACoAAAABgAAAAEAAADIAAAAASAAAAIAAADoAAAAAyAAAAIA" +
     76     "AAASAQAAAiAAAAgAAAAcAQAAACAAAAEAAADDAQAAAxAAAAEAAADYAQAAABAAAAEAAADcAQAA");
     77 
     78   /**
     79    * base64 encoded class/dex file for
     80    * package xyz;
     81    * public class Transform {
     82    *   public native void foo();
     83    *   public void bar() {
     84    *     // Make sure the methodID is before any of the ones in Transform
     85    *     art.Test1949.doNothing();
     86    *   }
     87    * }
     88    */
     89   private static final byte[] CLASS_BYTES_FINAL = Base64.getDecoder().decode(
     90     "yv66vgAAADUAFAoABAANCgAOAA8HABAHABEBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51" +
     91     "bWJlclRhYmxlAQADZm9vAQADYmFyAQAKU291cmNlRmlsZQEADlRyYW5zZm9ybS5qYXZhDAAFAAYH" +
     92     "ABIMABMABgEADXh5ei9UcmFuc2Zvcm0BABBqYXZhL2xhbmcvT2JqZWN0AQAMYXJ0L1Rlc3QxOTQ5" +
     93     "AQAJZG9Ob3RoaW5nACEAAwAEAAAAAAADAAEABQAGAAEABwAAAB0AAQABAAAABSq3AAGxAAAAAQAI" +
     94     "AAAABgABAAAAAgEBAAkABgAAAAEACgAGAAEABwAAABwAAAABAAAABLgAArEAAAABAAgAAAAGAAEA" +
     95     "AAAEAAEACwAAAAIADA==");
     96   private static final byte[] DEX_BYTES_FINAL = Base64.getDecoder().decode(
     97     "ZGV4CjAzNQBHXBiw7Hso1vnmaXE1VCV41f4+0aECixOgAgAAcAAAAHhWNBIAAAAAAAAAAAwCAAAK" +
     98     "AAAAcAAAAAQAAACYAAAAAQAAAKgAAAAAAAAAAAAAAAUAAAC0AAAAAQAAANwAAACkAQAA/AAAADQB" +
     99     "AAA8AQAATAEAAGABAABxAQAAgQEAAIQBAACJAQAAlAEAAJkBAAABAAAAAgAAAAMAAAAFAAAABQAA" +
    100     "AAMAAAAAAAAAAAAAAAcAAAABAAAAAAAAAAIAAAAAAAAAAgAAAAYAAAACAAAACAAAAAIAAAABAAAA" +
    101     "AQAAAAAAAAAEAAAAAAAAAPYBAAAAAAAAAQABAAEAAAAsAQAABAAAAHAQAQAAAA4AAQABAAAAAAAw" +
    102     "AQAABAAAAHEAAAAAAA4AAgAOAAQADgAGPGluaXQ+AA5MYXJ0L1Rlc3QxOTQ5OwASTGphdmEvbGFu" +
    103     "Zy9PYmplY3Q7AA9MeHl6L1RyYW5zZm9ybTsADlRyYW5zZm9ybS5qYXZhAAFWAANiYXIACWRvTm90" +
    104     "aGluZwADZm9vAFt+fkQ4eyJtaW4tYXBpIjoxLCJzaGEtMSI6IjkwZWYyMjkwNWMzZmVjY2FiMjMw" +
    105     "MzBhNmJkYzU2NTcwYTMzNWVmMDUiLCJ2ZXJzaW9uIjoidjEuMS44LWRldiJ9AAAAAQICgYAE/AED" +
    106     "AZQCAYECAAAAAAAMAAAAAAAAAAEAAAAAAAAAAQAAAAoAAABwAAAAAgAAAAQAAACYAAAAAwAAAAEA" +
    107     "AACoAAAABQAAAAUAAAC0AAAABgAAAAEAAADcAAAAASAAAAIAAAD8AAAAAyAAAAIAAAAsAQAAAiAA" +
    108     "AAoAAAA0AQAAACAAAAEAAAD2AQAAAxAAAAEAAAAIAgAAABAAAAEAAAAMAgAA");
    109 
    110   public static void run() throws Exception {
    111     Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
    112     doTest();
    113   }
    114 
    115   // A method with a methodID before anything in Transform.
    116   public static void doNothing() {}
    117 
    118   private static ClassLoader CreateClassLoader(byte[] clz, byte[] dex) throws Exception {
    119     if (isDalvik) {
    120       Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader");
    121       Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class);
    122       /* on Dalvik, this is a DexFile; otherwise, it's null */
    123       return (ClassLoader)ctor.newInstance(ByteBuffer.wrap(dex), Test1949.class.getClassLoader());
    124     } else {
    125       return new ClassLoader() {
    126         public Class<?> findClass(String name) throws ClassNotFoundException {
    127           if (name.equals("xyz.Transform")) {
    128             return defineClass(name, clz, 0, clz.length);
    129           } else {
    130             throw new ClassNotFoundException("Couldn't find class: " + name);
    131           }
    132         }
    133       };
    134     }
    135   }
    136 
    137   public static void doTest() throws Exception {
    138     Class c = CreateClassLoader(CLASS_BYTES_INIT, DEX_BYTES_INIT).loadClass("xyz.Transform");
    139     Redefinition.doCommonClassRedefinition(c, CLASS_BYTES_FINAL, DEX_BYTES_FINAL);
    140     System.out.println("Passed");
    141   }
    142 }
    143