@Override public void execute(ExecutionNode node, MethodState mState) { HeapItem item = mState.readRegister(register); mState.assignReturnRegister(item); }
public void reflect(MethodState mState) throws Exception { if (log.isDebugEnabled()) { log.debug("Reflecting {} with context:\n{}", method, mState); } Object returnValue; try { returnValue = invoke(mState); } catch (NullPointerException | ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // e.printStackTrace(); if (log.isWarnEnabled()) { log.warn("Failed to reflect {}: ", method, e); } if (log.isDebugEnabled()) { log.debug("Stack trace: ", e); } throw e; } if (!method.returnsVoid()) { HeapItem returnItem; if (returnValue != null && !ClassNameUtils.isPrimitive(method.getReturnType())) { returnItem = new HeapItem(returnValue, ClassNameUtils.toInternal(returnValue.getClass())); } else { returnItem = new HeapItem(returnValue, method.getReturnType()); } mState.assignReturnRegister(returnItem); } }
@Override public void execute(VirtualMachine vm, Op op, ExecutionContext context) { MethodState mState = context.getMethodState(); String argumentType = mState.peekParameter(0).getType(); VirtualType virtualType = vm.getClassManager().getVirtualType(argumentType); try { Class<?> value = vm.getClassLoader().loadClass(virtualType.getBinaryName()); mState.assignReturnRegister(value, RETURN_TYPE); } catch (ClassNotFoundException e) { throw new RuntimeException("Class not found: " + argumentType, e); } }
@Test public void unsafeClassNameReturnsClassAndHasNoSideEffects() throws Exception { String className = "Lunsafe/Class;"; SideEffect.Level level = SideEffect.Level.NONE; VirtualClass virtualClass = setupClass(className, false, level); String binaryClassName = "unsafe.Class"; doReturn(OBJECT_CLASS).when(classLoader).loadClass(binaryClassName); HeapItem item = new HeapItem(binaryClassName, CommonTypes.STRING); when(mState.peekParameter(0)).thenReturn(item); method.execute(vm, op, context); verify(mState, times(1)).assignReturnRegister(eq(OBJECT_CLASS), eq(CommonTypes.CLASS)); verify(context, times(1)).staticallyInitializeClassIfNecessary(virtualClass); assertEquals(level, method.getSideEffectLevel()); }
@Test public void existentSafeClassNameReturnsRealClassAndHasNoSideEffects() throws Exception { String className = "Ljava/lang/String;"; // genuinely safe to load SideEffect.Level level = SideEffect.Level.NONE; setupClass(className, true, level); String binaryClassName = "java.lang.String"; HeapItem item = new HeapItem(binaryClassName, CommonTypes.STRING); when(mState.peekParameter(0)).thenReturn(item); method.execute(vm, op, context); verify(mState, times(1)).assignReturnRegister(eq(STRING_CLASS), eq(CommonTypes.CLASS)); assertEquals(level, method.getSideEffectLevel()); }
@Test public void strongSideEffectsClassNameReturnsClassAndHasStrongSideEffects() throws Exception { String className = "Lstrong/Class;"; SideEffect.Level level = SideEffect.Level.STRONG; VirtualClass virtualClass = setupClass(className, false, level); String binaryClassName = "strong.Class"; doReturn(OBJECT_CLASS).when(classLoader).loadClass(binaryClassName); HeapItem item = new HeapItem(binaryClassName, CommonTypes.STRING); when(mState.peekParameter(0)).thenReturn(item); method.execute(vm, op, context); verify(mState, times(1)).assignReturnRegister(eq(OBJECT_CLASS), eq(CommonTypes.CLASS)); verify(context, times(1)).staticallyInitializeClassIfNecessary(virtualClass); assertEquals(level, method.getSideEffectLevel()); }
@Test public void unknownClassNameThrowsExceptionAndAssignsNothing() throws Exception { String className = "Lunknown/Class;"; SideEffect.Level level = SideEffect.Level.NONE; VirtualClass virtualClass = setupClass(className, false, level); String binaryName = "unknown.Class"; HeapItem item = new HeapItem(binaryName, CommonTypes.STRING); when(mState.peekParameter(0)).thenReturn(item); when(classManager.getVirtualClass(className)).thenThrow(new RuntimeException()); Throwable exception = mock(Throwable.class); when(exceptionFactory.build(eq(op), eq(ClassNotFoundException.class), eq(binaryName))).thenReturn(exception); method.execute(vm, op, context); assertEquals(1, method.getExceptions().size()); Throwable actualException = method.getExceptions().iterator().next(); assertEquals(exception, actualException); verify(mState, times(0)).assignReturnRegister(any(UnknownValue.class), eq(CommonTypes.CLASS)); assertEquals(SideEffect.Level.NONE, method.getSideEffectLevel()); }
@Override public void execute(VirtualMachine vm, Op op, ExecutionContext context) { MethodState mState = context.getMethodState(); HeapItem fieldItem = mState.peekParameter(0); HeapItem instanceItem = mState.peekParameter(1); Field field = (Field) fieldItem.getValue(); int accessFlags = field.getModifiers(); String fieldClassName = ClassNameUtils.toInternal(field.getDeclaringClass()); if (!field.isAccessible()) { VirtualType callingClass = context.getCallerContext().getMethod().getDefiningClass(); ClassManager classManager = vm.getClassManager(); VirtualClass fieldClass = classManager.getVirtualClass(fieldClassName); boolean hasAccess = checkAccess(callingClass, fieldClass, accessFlags, op, vm.getExceptionFactory()); if (!hasAccess) { return; } } Object instance = instanceItem.getValue(); HeapItem getItem = get(field, instance, fieldClassName, accessFlags, context, vm, op); mState.assignReturnRegister(getItem); }
mState.assignReturnRegister(value, RETURN_TYPE); } catch (ClassNotFoundException e) { Throwable exception = vm.getExceptionFactory().build(op, ClassNotFoundException.class, binaryClassName);