diff --git a/smalivm/src/main/java/org/cf/smalivm/MethodReflector.java b/smalivm/src/main/java/org/cf/smalivm/MethodReflector.java index 175fadb87..d72ff2e31 100644 --- a/smalivm/src/main/java/org/cf/smalivm/MethodReflector.java +++ b/smalivm/src/main/java/org/cf/smalivm/MethodReflector.java @@ -61,6 +61,10 @@ public static boolean isSafe(String typeDescriptor) { return false; } + public static boolean isUnsafeMethod(String methodDescriptor) { + return !UnsafeMethods.contains(methodDescriptor); + } + private static void loadSafeClasses() throws IOException { // Methods from safe classes must not have any side effects, e.g. any IO. List lines = ConfigurationLoader.loadConfig(SAFE_CLASSES_PATH); diff --git a/smalivm/src/main/java/org/cf/smalivm/opcode/NewArrayOpFactory.java b/smalivm/src/main/java/org/cf/smalivm/opcode/NewArrayOpFactory.java index ba8cbb80f..eb3a74424 100644 --- a/smalivm/src/main/java/org/cf/smalivm/opcode/NewArrayOpFactory.java +++ b/smalivm/src/main/java/org/cf/smalivm/opcode/NewArrayOpFactory.java @@ -9,9 +9,13 @@ import org.jf.dexlib2.builder.MethodLocation; import org.jf.dexlib2.iface.instruction.formats.Instruction22c; import org.jf.dexlib2.util.ReferenceUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class NewArrayOpFactory implements OpFactory { + private static final Logger log = LoggerFactory.getLogger(NewArrayOpFactory.class.getSimpleName()); + @Override public Op create(MethodLocation location, TIntObjectMap addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); @@ -27,7 +31,11 @@ public Op create(MethodLocation location, TIntObjectMap addressT boolean useLocalClass = false; if (classManager.isFrameworkClass(baseClassName)) { // Create arrays of LocalInstance - useLocalClass = classManager.isSafeFrameworkClass(baseClassName); + if (classManager.isSafeFrameworkClass(baseClassName)) { + useLocalClass = true; + } else { + log.warn("{} is framework but not safe; will treat as if it doesn't exist.", baseClassName); + } } else { useLocalClass = classManager.isLocalClass(baseClassName); } diff --git a/smalivm/src/main/resources/safe_classes.cfg b/smalivm/src/main/resources/safe_classes.cfg index 923c68abd..e1c10fcaa 100644 --- a/smalivm/src/main/resources/safe_classes.cfg +++ b/smalivm/src/main/resources/safe_classes.cfg @@ -1,3 +1,5 @@ +// Methods of any classes here are considered safe to reflect. + // Numbers + Math Ljava/lang/Boolean; Ljava/lang/Byte; @@ -27,12 +29,13 @@ Ljava/lang/StringBuilder; Ljava/util/Comparator; Ljava/util/Locale; Ljava/util/Properties; -// It probably wouldn't break anything to reflect this, but it may mean -// not all execution paths are taken. +// It probably wouldn't break anything to reflect this, but it may mean not all execution paths are taken. //Ljava/util/Random; Ljava/util/Scanner; Ljava/util/StringTokenizer; Ljava/util/UUID; +Ljava/util/concurrent/TimeUnit; + // Network diff --git a/smalivm/src/main/resources/safe_framework_classes.cfg b/smalivm/src/main/resources/safe_framework_classes.cfg index f87db3ce6..edfd76edd 100644 --- a/smalivm/src/main/resources/safe_framework_classes.cfg +++ b/smalivm/src/main/resources/safe_framework_classes.cfg @@ -1,4 +1,4 @@ -// Framework; +// Methods of these classes are safe to virtual execute. This implies instantiation. Landroid/security/Credentials; Landroid/security/IKeyChainAliasCallback; Landroid/security/IKeyChainAliasCallback$Stub; @@ -133,3 +133,8 @@ Landroid/graphics/Paint$Cap; Landroid/text/TextUtils$TruncateAt; Ljava/lang/Enum; + + +Ljava/lang/Object; + +Landroid/net/wifi/SupplicantState; diff --git a/smalivm/src/main/resources/unsafe_methods.cfg b/smalivm/src/main/resources/unsafe_methods.cfg index 53b692359..14eb24df2 100644 --- a/smalivm/src/main/resources/unsafe_methods.cfg +++ b/smalivm/src/main/resources/unsafe_methods.cfg @@ -1,2 +1,5 @@ // It's unsafe to assume this method will always return the same value. Ljava/lang/Math;->random()D + +// No sleeping on the job please. +Ljava/util/concurrent/TimeUnit;->sleep(J)V