package edu.columbia.cs.psl.vmvm.asm; import java.util.HashMap; import java.util.HashSet; import java.util.List; import edu.columbia.cs.psl.vmvm.Constants; import edu.columbia.cs.psl.vmvm.Instrumenter; import edu.columbia.cs.psl.vmvm.VMState; import edu.columbia.cs.psl.vmvm.VirtualRuntime; import edu.columbia.cs.psl.vmvm.asm.mvs.ChrootMethodVisitor; import edu.columbia.cs.psl.vmvm.asm.mvs.StaticFieldIsolatorMV; import edu.columbia.cs.psl.vmvm.asm.mvs.StaticFinalMutibleizer; import edu.columbia.cs.psl.vmvm.asm.mvs.UnconditionalChrootMethodVisitor; import edu.columbia.cs.psl.vmvm.asm.struct.EqFieldInsnNode; import edu.columbia.cs.psl.vmvm.asm.struct.EqMethodInsnNode; import edu.columbia.cs.psl.vmvm.asm.struct.EqMethodNode; import edu.columbia.cs.psl.vmvm.chroot.ChrootUtils; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.ClassVisitor; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.Label; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.MethodVisitor; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.Opcodes; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.Type; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.commons.GeneratorAdapter; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.tree.AnnotationNode; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.tree.FieldInsnNode; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.tree.FieldNode; import edu.columbia.cs.psl.vmvm.org.objectweb.asm.tree.MethodNode; import edu.columbia.cs.psl.vmvm.struct.MutableInstance; public abstract class VMVMClassVisitor extends ClassVisitor implements Opcodes, Constants { protected String className; private boolean useVMState; public VMVMClassVisitor(int api, ClassVisitor cv, boolean useVMState) { super(api, cv); this.useVMState = useVMState; } private boolean isClass; private int version; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { if((access & Opcodes.ACC_PRIVATE) != 0) { // System.out.println(access); // System.out.println(name); access = access & ~Opcodes.ACC_PRIVATE; access = access + Opcodes.ACC_PUBLIC; // System.out.println(access); } super.visit(version, access, name, signature, superName, interfaces); this.version = version; isClass = (access & Opcodes.ACC_INTERFACE) == 0; isEnum = (access & Opcodes.ACC_ENUM) != 0; } @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { if((access & Opcodes.ACC_PRIVATE) != 0) { // System.out.println(access); // System.out.println(name); access = access & ~Opcodes.ACC_PRIVATE; access = access + Opcodes.ACC_PUBLIC; // System.out.println(access); } super.visitInnerClass(name, outerName, innerName, access); } public int getVersion() { return version; } protected HashMap<EqMethodNode, MethodNode> renamedMethodsToCover = new HashMap<>(); private HashSet<EqMethodInsnNode> chrootMethodsToGen = new HashSet<>(); public void addChrootMethodToGen(EqMethodInsnNode mi) { chrootMethodsToGen.add(mi); } public void addStaticCloneWrapper(String cloneMethodName, HashSet<EqFieldInsnNode> fieldsToClone) { staticCloneMethodsToGen.put(cloneMethodName, fieldsToClone); } private HashMap<String, HashSet<EqFieldInsnNode>> staticCloneMethodsToGen = new HashMap<>(); // protected void generateFinalHackMethod() // { // MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC, Constants.VMVM_STATIC_RESET_METHOD, "(L"+className+";)V", null,null); // GeneratorAdapter gmv = new GeneratorAdapter(mv, Opcodes.ACC_PUBLIC, Constants.VMVM_STATIC_RESET_METHOD, "(L"+className+";)V"); // // for(Object o : Instrumenter.getClassNode(className).fields) // { // FieldNode fn = (FieldNode) o; // if((fn.access & Opcodes.ACC_STATIC) == 0) // { // if((fn.access & Opcodes.ACC_FINAL) == 0) // { // gmv.loadThis(); // gmv.loadArg(0); // gmv.visitFieldInsn(GETFIELD, className, fn.name, fn.desc); // gmv.visitFieldInsn(PUTFIELD, className, fn.name, fn.desc); // } // else if(fn.desc.length() > 2 && Instrumenter.instrumentedClasses.containsKey(Type.getType(fn.desc).getInternalName())) // { // gmv.loadThis(); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.loadArg(0); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(fn.desc).getInternalName(), Constants.VMVM_STATIC_RESET_METHOD, "("+fn.desc+")V"); // } // else if(fn.desc.startsWith("[")) // { // gmv.loadArg(0); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.push(0); // gmv.loadThis(); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.push(0); // gmv.loadArg(0); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitInsn(ARRAYLENGTH); //// System.arraycopy(src, srcPos, dest, destPos, length) // // gmv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"); // } else if (fn.desc.length() > 1) { // try { // Class<?> c = Class.forName(Type.getType(fn.desc) // .getClassName()); // if (Collection.class.isAssignableFrom(c)) { // gmv.loadThis(); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitInsn(DUP); // String fieldType = Type.getType(fn.desc).getInternalName(); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "clear", "()V"); // gmv.loadArg(0); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "addAll", "("+Type.getDescriptor(Collection.class)+")Z"); // gmv.visitInsn(POP); // } // else if(Map.class.isAssignableFrom(c)) // { // gmv.loadThis(); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitInsn(DUP); // String fieldType = Type.getType(fn.desc).getInternalName(); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "clear", "()V"); // gmv.loadArg(0); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "putAll", "("+Type.getDescriptor(Map.class)+")V"); // } // else if(fn.desc.equals("Ljava/lang/ThreadLocal;")) // { // gmv.loadThis(); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.loadArg(0); // gmv.visitFieldInsn(Opcodes.GETFIELD, className, fn.name, fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ThreadLocal", "get", "()Ljava/lang/Object;"); // gmv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ThreadLocal", "set", "(Ljava/lang/Object;)V"); // } // } catch (Exception ex) // { // ex.printStackTrace(); // } // } // } // } // gmv.returnValue(); // gmv.visitMaxs(0, 0); // gmv.visitEnd(); // // } protected void generateClinit(boolean callClinit) { MethodVisitor mv = super.visitMethod( Opcodes.ACC_STATIC, "<clinit>", "()V", null,null); GeneratorAdapter gmv = new GeneratorAdapter(mv, Opcodes.ACC_STATIC, "<clinit>", "()V"); StaticFinalMutibleizer fmv = new StaticFinalMutibleizer(gmv, Opcodes.ACC_STATIC, className, "<clinit>", "()V"); if(!isAClass()) for(Object o : Instrumenter.getClassNode(className).fields) { FieldNode fn = (FieldNode) o; if(fn.value != null) { fmv.visitLdcInsn(fn.value); fmv.visitFieldInsn(PUTSTATIC, className, fn.name, fn.desc); } else { gmv.visitTypeInsn(NEW, Type.getInternalName(MutableInstance.class)); gmv.visitInsn(DUP); gmv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(MutableInstance.class), "<init>", "()V", false); gmv.visitFieldInsn(PUTSTATIC, className, fn.name, Type.getDescriptor(MutableInstance.class)); } } String classWithResetMethod = className; if(!isAClass()) classWithResetMethod += "$vmvmReseter"; // if(callClinit) { // if(StaticFieldIsolatorMV.CLINIT_ORDER_DEBUG) // { // Label l0 = new Label(); // Label l1 = new Label(); // Label l2 = new Label(); // Label l3 = new Label(); // gmv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable"); // gmv.visitLabel(l0); // gmv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); // gmv.visitLdcInsn("called real, actual clinit in " + className); // gmv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); // gmv.visitLabel(l1); // gmv.visitJumpInsn(GOTO, l3); // gmv.visitLabel(l2); // mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Exception", "printStackTrace", "()V"); // gmv.visitLabel(l3); // } gmv.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); gmv.visitFieldInsn(PUTSTATIC, classWithResetMethod, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;"); gmv.visitMethodInsn(INVOKESTATIC, classWithResetMethod, Constants.VMVM_STATIC_RESET_METHOD, "()V", false); gmv.visitInsn(ACONST_NULL); gmv.visitFieldInsn(PUTSTATIC, classWithResetMethod, Constants.VMVM_RESET_IN_PROGRESS, "Ljava/lang/Thread;"); } gmv.returnValue(); gmv.visitMaxs(0, 0); gmv.visitEnd(); if(!callClinit && isAClass()) { mv = super.visitMethod( Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, Constants.VMVM_STATIC_RESET_METHOD, "()V", null,null); gmv = new GeneratorAdapter(mv, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, Constants.VMVM_STATIC_RESET_METHOD, "()V"); StaticFieldIsolatorMV gmvv = new StaticFieldIsolatorMV(gmv, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, Constants.VMVM_STATIC_RESET_METHOD, "()V", this, null); gmvv.visitCode(); gmvv.visitInsn(RETURN); gmv.visitMaxs(0, 0); gmvv.visitEnd(); } } // protected void generateStaticFieldCloneMethods(boolean callClinit) // { // MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, Constants.VMVM_STATIC_RESET_METHOD, "()V", null,null); // GeneratorAdapter gmv = new GeneratorAdapter(mv, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, Constants.VMVM_STATIC_RESET_METHOD, "()V"); // if(callClinit) // gmv.visitMethodInsn(INVOKESTATIC, className, "_clinit", "()V"); // for(EqFieldInsnNode fn : staticFieldsToClone) // { // if(fn.name.equals("$assertionsDisabled")) // continue; // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name + Constants.BEEN_CLONED_FIELD, "Z"); // Label continu = new Label(); // gmv.visitJumpInsn(IFEQ, continu); // if(fn.isFinal()) // { // if(fn.desc.startsWith("[")) // { // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name+Constants.SANDBOX_SUFFIX, fn.desc); // gmv.push(0); // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name, fn.desc); // gmv.push(0); // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name, fn.desc); // gmv.visitInsn(ARRAYLENGTH); //// System.arraycopy(src, srcPos, dest, destPos, length) // // gmv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"); // } // else if(fn.desc.length() > 2 && Instrumenter.instrumentedClasses.containsKey(Type.getType(fn.desc).getInternalName())) // { // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name, fn.desc); // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name+Constants.SANDBOX_SUFFIX, fn.desc); // gmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(fn.desc).getInternalName(), Constants.VMVM_STATIC_RESET_METHOD, "("+fn.desc+")V"); // } // else if(fn.desc.length() > 2){ // try { // Class<?> c = Class.forName(Type.getType(fn.desc) // .getClassName()); // if (Collection.class.isAssignableFrom(c)) { // gmv.visitFieldInsn(Opcodes.GETSTATIC, className, fn.name, fn.desc); // gmv.visitInsn(DUP); // String fieldType = Type.getType(fn.desc).getInternalName(); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "clear", "()V"); // gmv.visitFieldInsn(Opcodes.GETSTATIC, className, fn.name+Constants.SANDBOX_SUFFIX, fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "addAll", "("+Type.getDescriptor(Collection.class)+")Z"); // gmv.visitInsn(POP); // } // else if(Map.class.isAssignableFrom(c)) // { // gmv.visitFieldInsn(Opcodes.GETSTATIC, className, fn.name, fn.desc); // gmv.visitInsn(DUP); // String fieldType = Type.getType(fn.desc).getInternalName(); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "clear", "()V"); // gmv.visitFieldInsn(Opcodes.GETSTATIC, className, fn.name+Constants.SANDBOX_SUFFIX, fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, fieldType, "putAll", "("+Type.getDescriptor(Map.class)+")V"); // } // else if(fn.desc.equals("Ljava/lang/ThreadLocal;")) // { // gmv.visitFieldInsn(Opcodes.GETSTATIC, className, fn.name, fn.desc); // gmv.visitFieldInsn(Opcodes.GETSTATIC, className, fn.name+Constants.SANDBOX_SUFFIX, fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ThreadLocal", "get", "()Ljava/lang/Object;"); // gmv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ThreadLocal", "set", "(Ljava/lang/Object;)V"); // } // } catch (Exception ex) // { // ex.printStackTrace(); // } // } // } // else // { // gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name+Constants.SANDBOX_SUFFIX, fn.desc); // gmv.visitFieldInsn(Opcodes.PUTSTATIC, fn.owner, fn.name, fn.desc); // } // gmv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // gmv.visitLdcInsn("reseting>"+fn.owner+ "."+fn.name+" "+fn.desc); // gmv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); //// gmv.visitInsn(ICONST_0); //// gmv.visitFieldInsn(Opcodes.PUTSTATIC, fn.owner, fn.name + Constants.BEEN_CLONED_FIELD, "Z"); // gmv.visitLabel(continu); // } // gmv.returnValue(); // gmv.visitMaxs(0, 0); // gmv.visitEnd(); // } protected void generateStaticCloneMethods() { for (String methodName : staticCloneMethodsToGen.keySet()) { MethodVisitor mv = super.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, methodName, "(I)V", null, null); GeneratorAdapter gmv = new GeneratorAdapter(mv, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, methodName, "(I)V"); // InvivoAdapter iv = new InvivoAdapter(Opcodes.ASM4, gmv, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, mName, captureDesc, this.className); gmv.visitCode(); if(staticCloneMethodsToGen != null && methodName != null && staticCloneMethodsToGen.get(methodName) != null) for (FieldInsnNode fn : staticCloneMethodsToGen.get(methodName)) { gmv.visitFieldInsn(Opcodes.GETSTATIC, fn.owner, fn.name, fn.desc); gmv.loadArg(0); Label[] lbls = new Label[Instrumenter.MAX_SANDBOXES + 1]; for (int i = 0; i < lbls.length; i++) lbls[i] = new Label(); Label endOfTbl = new Label(); gmv.visitTableSwitchInsn(0, Instrumenter.MAX_SANDBOXES, lbls[0], lbls); for (int i = 0; i < lbls.length; i++) { gmv.visitLabel(lbls[i]); gmv.visitFieldInsn(Opcodes.PUTSTATIC, fn.owner, fn.name + "_vmvm_" + i, fn.desc); gmv.visitJumpInsn(GOTO, endOfTbl); } gmv.visitLabel(endOfTbl); } gmv.returnValue(); gmv.visitMaxs(0, 0); gmv.visitEnd(); } } protected void generateChrootMethods() { Object[] o = new Object[4]; o[1] = null; generateRegularChrootMethods(); generateParentConstructorChrootMethods(); } private void generateParentConstructorChrootMethods() { for (EqMethodInsnNode m : chrootMethodsToGen) { if(m.flag != EqMethodInsnNode.FLAG_SUPER_INVOKE_CHROOT) continue; String mName = ChrootUtils.getCaptureInitParentMethodName(m); String captureDesc = "("; for (Type t : Type.getArgumentTypes(m.desc)) captureDesc += t.getDescriptor(); if(useVMState) captureDesc += Type.getDescriptor(VMState.class); captureDesc += ")[Ljava/lang/Object;"; MethodVisitor mv = super.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, mName, captureDesc, null, null); GeneratorAdapter gmv = new GeneratorAdapter(mv, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, mName, captureDesc); gmv.visitCode(); String data = ChrootMethodVisitor.fsMethods.get(m.owner + "." + m.name + m.desc); if (data.length() == 1) { gmv.visitIntInsn(BIPUSH, Type.getArgumentTypes(m.desc).length); gmv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); int n = Integer.parseInt(data); Type[] args = Type.getArgumentTypes(captureDesc); for (int i = 0; i < args.length - (useVMState ? 1 : 0); i++) { gmv.visitInsn(DUP); gmv.visitIntInsn(BIPUSH, i); gmv.loadArg(i); if (i == n) { if(useVMState) gmv.loadArg(args.length - 1); gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ChrootUtils.class), "ensureSafePath", "(Ljava/lang/String;" + (useVMState ? Type.getDescriptor(VMState.class) :"") + ")Ljava/lang/String;", false); } gmv.visitInsn(AASTORE); } gmv.returnValue(); } else if (data.equals("URI")) { Type[] args = Type.getArgumentTypes(captureDesc); for (int i = 0; i < args.length; i++) gmv.loadArg(i); gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ChrootUtils.class), "ensureSafeURIArrayReturn", captureDesc, false); } else if (data.equals("URL")) { Type[] args = Type.getArgumentTypes(captureDesc); for (int i = 0; i < args.length; i++) gmv.loadArg(i); gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ChrootUtils.class), "ensureSafeURLArrayReturn", captureDesc, false); } else if (data.equals("FS")) { System.out.println("Warn: app uses " + m.owner+"."+m.name + m.desc); } gmv.returnValue(); gmv.visitMaxs(0, 0); gmv.visitEnd(); } } private void generateRegularChrootMethods() { for (EqMethodInsnNode m : chrootMethodsToGen) { if(m.flag == EqMethodInsnNode.FLAG_SUPER_INVOKE_CHROOT) continue; String mName = ChrootUtils.getCaptureMethodName(m); String captureDesc = "("; for (Type t : Type.getArgumentTypes(m.desc)) captureDesc += t.getDescriptor(); if(useVMState) captureDesc += Type.getDescriptor(VMState.class); if (m.name.equals("<init>")) captureDesc += ")" + Type.getReturnType("L" + m.owner + ";").getDescriptor(); else captureDesc += ")" + Type.getReturnType(m.desc).getDescriptor(); MethodVisitor mv = super.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, mName, captureDesc, null, null); GeneratorAdapter gmv = new GeneratorAdapter(mv, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, mName, captureDesc); gmv.visitCode(); String originalDesc = m.desc; if (m.name.equals("<init>")) { if (!m.owner.contains("URL") && !m.owner.contains("URI")) { gmv.visitTypeInsn(NEW, Type.getReturnType(m.owner).getInternalName()); gmv.visitInsn(DUP); } m.desc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getArgumentTypes(m.desc)); } String data = ChrootMethodVisitor.fsMethods.get(m.owner + "." + m.name + m.desc); if (data.length() == 1) { int n = Integer.parseInt(data); Type[] args = Type.getArgumentTypes(captureDesc); for (int i = 0; i < args.length - (useVMState ? 1 : 0); i++) { gmv.loadArg(i); if (i == n) { if(useVMState) gmv.loadArg(args.length - 1); gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ChrootUtils.class), "ensureSafePath", "(Ljava/lang/String;" + (useVMState ? Type.getDescriptor(VMState.class) :"") + ")Ljava/lang/String;", false); } } if(UnconditionalChrootMethodVisitor.fsOutputMethods.contains(m.owner + "." + m.name + m.desc)) { UnconditionalChrootMethodVisitor.sandboxCallToFSOutputMethod(gmv, m.getOpcode(), m.owner, m.name, m.desc); } else gmv.visitMethodInsn(m.getOpcode(), m.owner, m.name, m.desc, false); } else if (data.equals("URI")) { Type[] args = Type.getArgumentTypes(captureDesc); for (int i = 0; i < args.length; i++) gmv.loadArg(i); gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ChrootUtils.class), "ensureSafeURI", captureDesc, false); } else if (data.equals("URL")) { Type[] args = Type.getArgumentTypes(captureDesc); for (int i = 0; i < args.length; i++) gmv.loadArg(i); gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ChrootUtils.class), "ensureSafeURL", captureDesc, false); } else if (data.equals("FS")) { } gmv.returnValue(); gmv.visitMaxs(0, 0); gmv.visitEnd(); } } protected void generateCoverMethods() { for (MethodNode m : renamedMethodsToCover.keySet()) { // if(Instrumenter.getMethodNode(thisClassInfo, m.name, m.desc) != null) // { // continue; // } List<String> list = (List<String>) m.exceptions; String[] exceptions = new String[list.size()]; exceptions = list.toArray(exceptions); MethodVisitor mv = super.visitMethod(m.access, m.name, m.desc, m.signature, exceptions); GeneratorAdapter gmv = new GeneratorAdapter(mv, m.access, m.name, m.desc); MethodNode mOrig = renamedMethodsToCover.get(m); for (Object o : mOrig.visibleAnnotations) { AnnotationNode an = (AnnotationNode) o; an.accept(gmv.visitAnnotation(an.desc, true)); } for (Object o : mOrig.invisibleAnnotations) { AnnotationNode an = (AnnotationNode) o; an.accept(gmv.visitAnnotation(an.desc, false)); } gmv.visitCode(); if ((m.access & Opcodes.ACC_ABSTRACT) == 0) { if ((m.access & Opcodes.ACC_STATIC) == 0) //not-static { gmv.loadThis(); } Type[] args = Type.getArgumentTypes(m.desc); for (int i = 0; i < args.length; i++) { gmv.loadArg(i); } gmv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(VirtualRuntime.class), "getVMState", "()" + Type.getDescriptor(VMState.class), false); gmv.visitMethodInsn((m.access & Opcodes.ACC_STATIC) != 0 ? Opcodes.INVOKESTATIC : m.name.equals("<init>") ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL, className, (!"<init>".equals(renamedMethodsToCover.get(m).name) && !"<clinit>".equals(renamedMethodsToCover.get(m).name) ? "_" : "") + renamedMethodsToCover.get(m).name, renamedMethodsToCover.get(m).desc, false); gmv.returnValue(); } gmv.visitMaxs(0, 0); gmv.visitEnd(); } } public String getClassName() { return className; } public abstract boolean hasExtraInterface(); public abstract byte[] getExtraInterface(); private HashSet<EqFieldInsnNode> staticFieldsToClone = new HashSet<>(); public void addStaticFieldsToClone( HashSet<EqFieldInsnNode> staticFieldsToClone) { this.staticFieldsToClone.addAll(staticFieldsToClone); } public boolean isAClass() { return isClass; } private boolean isEnum; public boolean isEnum() { return isEnum; } }