@Nonnull public boolean isNull() { return getValue() == null; }
@Override protected void execute(VirtualMachine vm, Op op, MethodState mState) { // This is a virtual method, so register 0 contains a reference to an instance of Ljava/io/PrintStream; // Register 1 should have the string to print. HeapItem item = mState.peekParameter(1); Object value = item.getValue(); String valueStr = (String) value; System.out.println(valueStr); }
public static Set<String> getDeclaredAndValueTypeNames(HeapItem item) { Set<String> types = new HashSet<>(3); types.add(item.getType()); Object value = item.getValue(); if (!item.isUnknown() && value != null) { types.add(ClassNameUtils.toInternal(value.getClass())); } return types; }
public static void setRegisterMock(MethodState mState, int register, Object value, String type) { HeapItem item = mock(HeapItem.class); when(item.getValue()).thenReturn(value); if (CommonTypes.INTEGER.equals(type) && value instanceof Number) { when(item.asInteger()).thenReturn((Integer) value); } else if (value instanceof UnknownValue) { when(item.isUnknown()).thenReturn(true); } when(item.getComponentBase()).thenReturn(ClassNameUtils.getComponentBase(type)); when(item.getType()).thenReturn(type); when(mState.readRegister(eq(register))).thenReturn(item); }
@Test public void canFloatToDouble() { Float value = 11204.0345F; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("F"); when(instruction.getOpcode()).thenReturn(Opcode.FLOAT_TO_DOUBLE); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.doubleValue(), "D"))); }
@Test public void canFloatToInt() { Float value = 11204.0345F; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("F"); when(instruction.getOpcode()).thenReturn(Opcode.FLOAT_TO_INT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.intValue(), "I"))); }
@Test public void canLongToDouble() { Long value = 112040345L; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("J"); when(instruction.getOpcode()).thenReturn(Opcode.LONG_TO_DOUBLE); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.doubleValue(), "D"))); }
@Test public void canLongToInt() { Long value = 112040345L; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("J"); when(instruction.getOpcode()).thenReturn(Opcode.LONG_TO_INT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.intValue(), "I"))); }
@Test public void canFloatToLong() { Float value = 11204.0345F; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("F"); when(instruction.getOpcode()).thenReturn(Opcode.FLOAT_TO_LONG); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.longValue(), "J"))); }
@Test public void canLongToFloat() { Long value = 112040345L; when(item.getValue()).thenReturn(value); when(item.getType()).thenReturn("J"); when(instruction.getOpcode()).thenReturn(Opcode.LONG_TO_FLOAT); op = (UnaryMathOp) opFactory.create(location, addressToLocation, vm); op.execute(node, mState); verify(mState, times(1)).assignRegister(eq(REGISTER_A), eq(new HeapItem(value.floatValue(), "F"))); }
@Test public void canCreate2DLocalInstanceArray() throws ClassNotFoundException { int length = 5; initial.setRegisters(0, length, "I"); ExecutionGraph graph = VMTester.execute(CLASS_NAME, "create2DLocalInstanceArray()V", initial); HeapItem consensus = graph.getTerminatingRegisterConsensus(0); assertEquals("[[" + CLASS_NAME, consensus.getType()); assertEquals(length, Array.getLength(consensus.getValue())); Class<?> actualClass = consensus.getValue().getClass(); assertEquals("[[" + CLASS_NAME, actualClass.getName()); }
public static BuilderInstruction buildConstant(int address, ExecutionGraphManipulator manipulator) { DexBuilder dexBuilder = manipulator.getDexBuilder(); OneRegisterInstruction instruction = (OneRegisterInstruction) manipulator.getInstruction(address); int register = instruction.getRegisterA(); HeapItem item = manipulator.getRegisterConsensus(address, register); Object value = item.getValue(); String type = item.isPrimitive() ? item.getType() : item.getUnboxedValueType(); BuilderInstruction constant = buildConstant(value, type, register, dexBuilder); return constant; }
@Test public void canInvokeImplemenetedAbstractMethod() throws VirtualMachineException { String methodName = "abstractMethod()Ljava/lang/String;"; ExecutionGraph graph = vm.execute(CLASS_NAME + "->" + methodName); HeapItem item = graph.getTerminatingRegisterConsensus(MethodState.ReturnRegister); String value = (String) item.getValue(); assertEquals(EXPECTED_VALUE, value); }
private void executeLocalObjectInit(MethodState callerMethodState) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { int instanceRegister = parameterRegisters[0]; HeapItem instanceItem = callerMethodState.peekRegister(instanceRegister); UninitializedInstance uninitializedInstance = (UninitializedInstance) instanceItem.getValue(); VirtualType instanceType = uninitializedInstance.getType(); // Create a Java class of the true type Class<?> klazz = vm.getClassLoader().loadClass(instanceType.getBinaryName()); Object newInstance = ObjectInstantiator.newInstance(klazz); HeapItem newInstanceItem = new HeapItem(newInstance, instanceType.getName()); callerMethodState.assignRegisterAndUpdateIdentities(instanceRegister, newInstanceItem); }
private static void testException(String methodDescriptor, Class<?> exceptionClass, String exceptionMessage, VMState initial) { ExecutionGraph graph = VMTester.execute(CLASS_NAME, methodDescriptor, initial); HeapItem item = graph.getTerminatingRegisterConsensus(0); Assert.assertEquals(exceptionClass, item.getValue().getClass()); Assert.assertEquals(ClassNameUtils.toInternal(exceptionClass), item.getType()); Assert.assertEquals(exceptionMessage, ((Throwable) item.getValue()).getMessage()); assertFalse("Should not reach next instruction in non-exception execution path", graph.wasAddressReached(1)); MethodState mState = graph.getNodePile(0).get(0).getContext().getMethodState(); Assert.assertEquals(0, mState.getRegistersAssigned().length); }
private static void testException(String methodDescriptor, Class<?> exceptionClass, String exceptionMessage, VMState initial) { ExecutionGraph graph = VMTester.execute(CLASS_NAME, methodDescriptor, initial); HeapItem item = graph.getTerminatingRegisterConsensus(0); Assert.assertEquals(exceptionClass, item.getValue().getClass()); Assert.assertEquals(ClassNameUtils.toInternal(exceptionClass), item.getType()); Assert.assertEquals(exceptionMessage, ((Throwable) item.getValue()).getMessage()); assertFalse("Should not reach next instruction in non-exception execution path", graph.wasAddressReached(1)); MethodState mState = graph.getNodePile(0).get(0).getContext().getMethodState(); Assert.assertEquals(0, mState.getRegistersAssigned().length); }
@Test public void invokeGetClassOnSelfReturnsCorrectClass() throws InstantiationException, IllegalAccessException, ClassNotFoundException { VirtualMachine vm = VMTester.spawnVM(); Class<?> virtualClass = vm.getClassLoader().loadClass(CLASS_NAME_BINARY); Object instance = virtualClass.newInstance(); initial.setRegisters(0, instance, CLASS_NAME); ExecutionGraph graph = VMTester.execute(vm, CLASS_NAME, "invokeGetClassOnThis()V", initial); HeapItem consensus = graph.getTerminatingRegisterConsensus(MethodState.ResultRegister); assertEquals(instance.getClass(), consensus.getValue()); } }
@Test public void cloningNullWithArrayCloneThrowsException() { // Calling with Object clone (and not [Object clone) will always throw a NPE because // there's not enough type information to know it's an array clone. initial.setRegisters(0, null, "[Ljava/lang/Object;"); ExecutionGraph graph = VMTester.execute(CLASS_NAME, "invokeArrayClone()V", initial); HeapItem item = graph.getTerminatingRegisterConsensus(0); Class<?> exceptionClass = NullPointerException.class; Assert.assertEquals(exceptionClass, item.getValue().getClass()); Assert.assertEquals(ClassNameUtils.toInternal(exceptionClass), item.getType()); int[] expectedAddresses = new int[] { 0, 5, 6 }; VMTester.testVisitation(graph, expectedAddresses); }
private static void testException(String methodDescriptor, Class<?> exceptionClass, VMState initial) { ExecutionGraph graph = VMTester.execute(CLASS_NAME, methodDescriptor, initial); HeapItem item = graph.getTerminatingRegisterConsensus(0); Assert.assertEquals(exceptionClass, item.getValue().getClass()); Assert.assertEquals(ClassNameUtils.toInternal(exceptionClass), item.getType()); assertFalse("Should not reach next instruction in non-exception execution path", graph.wasAddressReached(2)); MethodState mState = graph.getNodePile(0).get(0).getContext().getMethodState(); Assert.assertEquals(0, mState.getRegistersAssigned().length); }
private static void testException(String methodDescriptor, Class<?> exceptionClass) { ExecutionGraph graph = VMTester.execute(CLASS_NAME, methodDescriptor); HeapItem item = graph.getTerminatingRegisterConsensus(0); assertEquals(exceptionClass, item.getValue().getClass()); assertEquals(ClassNameUtils.toInternal(exceptionClass), item.getType()); assertFalse(graph.wasAddressReached(2)); MethodState mState = graph.getNodePile(0).get(0).getContext().getMethodState(); assertEquals(0, mState.getRegistersAssigned().length); }