@Override public void visit(Branch.Condition.Nil cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.addr()))); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(IFNULL, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(IFNONNULL, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
@Override public void visit(Branch.Condition.Bool cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.addr()))); il.add(ConversionMethods.booleanValueOf()); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(cond.expected() ? IFNE : IFEQ, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(cond.expected() ? IFEQ : IFNE, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
@Override public void visit(Branch.Condition.NumLoopEnd cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.var()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(new VarInsnNode(ALOAD, slot(cond.limit()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(new VarInsnNode(ALOAD, slot(cond.step()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(DispatchMethods.continueLoop()); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(IFEQ, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(IFNE, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
private void transformDamageItem(MethodNode method) { InsnList postEvent = new InsnList(); LabelNode label = new LabelNode(new Label()); postEvent.add(new TypeInsnNode(Opcodes.NEW, DAMAGE_ITEM_EVENT.getInternalName())); postEvent.add(new InsnNode(Opcodes.DUP)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 2)); postEvent.add(new VarInsnNode(Opcodes.ILOAD, 1)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 0)); postEvent.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, DAMAGE_ITEM_EVENT_INIT.getOwnerInternalName(), DAMAGE_ITEM_EVENT_INIT.getEnvName(), DAMAGE_ITEM_EVENT_INIT.getDesc(), false)); postEvent.add(new VarInsnNode(Opcodes.ASTORE, 3)); postEvent.add(new FieldInsnNode(Opcodes.GETSTATIC, EVENTHANDLER_DAMAGE_ITEM.getOwnerInternalName(), EVENTHANDLER_DAMAGE_ITEM.getEnvName(), EVENTHANDLER_DAMAGE_ITEM.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 3)); postEvent.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, POST.getOwnerInternalName(), POST.getEnvName(), POST.getDesc(), false)); postEvent.add(new JumpInsnNode(Opcodes.IFEQ, label)); postEvent.add(new InsnNode(Opcodes.RETURN)); postEvent.add(label); postEvent.add(new FrameNode(Opcodes.F_APPEND, 1, new Object[] {DAMAGE_ITEM_EVENT.getInternalName()}, 0, null)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 3)); postEvent.add(new FieldInsnNode(Opcodes.GETFIELD, DAMAGE.getOwnerInternalName(), DAMAGE.getEnvName(), DAMAGE.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ISTORE, 1)); method.instructions.insert(postEvent); }
private void updateFrames(int implVarIndex) { AbstractInsnNode next = instructions.getFirst(); while (next != null) { AbstractInsnNode node = next; next = next.getNext(); if (node instanceof FrameNode) { FrameNode frameNode = (FrameNode) node; Collection<Object> locals = new ArrayList<>(); for (Object value : frameNode.local) { locals.add(value); if (isLong(value)) { locals.add(TOP); } } Object[] locals1 = convertValues(appendValue(ensureSize(locals.toArray(), implVarIndex), "org/jephyr/continuation/easyflow/ContinuationImpl")); List<Object> stack = frameNode.stack; instructions.set(node, new FrameNode(F_NEW, locals1.length, locals1, stack.size(), stack.toArray())); } } }
/** * adds a compressed frame to the stack * * @param stackArguments the argument types on the stack, represented as * "class path names" e.g java/lang/RuntimeException */ public CodeBlock frame_same(final Object... stackArguments) { final int type; switch (stackArguments.length) { case 0: type = Opcodes.F_SAME; break; case 1: type = Opcodes.F_SAME1; break; default: throw new IllegalArgumentException("same frame should have 0" + " or 1 arguments on stack"); } instructionList.add(new FrameNode(type, 0, null, stackArguments.length, stackArguments)); return this; }
public static void acceptFn(FrameNode fn, MethodVisitor mv) { switch (fn.type) { case Opcodes.F_NEW: case Opcodes.F_FULL: case TaintUtils.RAW_INSN: mv.visitFrame(fn.type, fn.local.size(), asArray(fn.local), fn.stack.size(), asArray(fn.stack)); break; case Opcodes.F_APPEND: mv.visitFrame(fn.type, fn.local.size(), asArray(fn.local), 0, null); break; case Opcodes.F_CHOP: mv.visitFrame(fn.type, fn.local.size(), null, 0, null); break; case Opcodes.F_SAME: mv.visitFrame(fn.type, 0, null, 0, null); break; case Opcodes.F_SAME1: mv.visitFrame(fn.type, 0, null, 1, asArray(fn.stack)); break; } }
/** * * @param descOfDest */ public void registerTaintedArray() { super.visitInsn(SWAP); Label isnull = new Label(); Label ok = new Label(); FrameNode fn2 = getCurrentFrameNode(); super.visitInsn(DUP); super.visitJumpInsn(IFNULL, isnull); super.visitInsn(DUP_X1); super.visitInsn(SWAP); Type onTop = getTopOfStackType(); String wrapper = (String) TaintUtils.getShadowTaintTypeForFrame(onTop.getDescriptor()); super.visitMethodInsn(INVOKEVIRTUAL, wrapper, "ensureVal", "("+onTop.getDescriptor()+")V", false); FrameNode fn = getCurrentFrameNode(); super.visitJumpInsn(GOTO, ok); super.visitLabel(isnull); acceptFn(fn2); super.visitInsn(SWAP); super.visitInsn(POP); super.visitLabel(ok); acceptFn(fn); //A }
@Override public void visitLabel(Label label) { // if (curLabel >= 0) if (DEBUG) System.out.println("Visit label: " + curLabel + " analyzer: " + analyzer.stack + " inframes size " + inFrames.size() + " " + outFrames.size()); if (analyzer.locals == null || analyzer.stack == null) inFrames.add(new FrameNode(0, 0, new Object[0], 0, new Object[0])); else inFrames.add(new FrameNode(0, analyzer.locals.size(), analyzer.locals.toArray(), analyzer.stack.size(), analyzer.stack.toArray())); // if (outFrames.size() <= curLabel) { // if(analyzer.stack == null) outFrames.add(null); if (curLabel > 0 && outFrames.get(curLabel - 1) == null && analyzer.stack != null) outFrames.set(curLabel - 1, new FrameNode(0, analyzer.locals.size(), analyzer.locals.toArray(), analyzer.stack.size(), analyzer.stack.toArray())); if (DEBUG) System.out.println("Added outframe for " + (outFrames.size() - 1) + " : " + analyzer.stack); // } super.visitLabel(label); curLabel++; }
public void patchMethod(MethodNode methodNode, String patchName, String clazzName) { methodNode.desc = methodNode.desc.replace(patchName, clazzName); for (Iterator<AbstractInsnNode> iterator = methodNode.instructions.iterator(); iterator.hasNext();) { AbstractInsnNode insn = iterator.next(); if (insn instanceof TypeInsnNode) { TypeInsnNode type = (TypeInsnNode) insn; type.desc = replace(type.desc, patchName, clazzName); } else if (insn instanceof FieldInsnNode) { FieldInsnNode field = (FieldInsnNode) insn; field.owner = replace(field.owner, patchName, clazzName); } else if (insn instanceof MethodInsnNode) { MethodInsnNode method = (MethodInsnNode) insn; if (method.owner.equals(patchName) && method.getOpcode() == INVOKEVIRTUAL) method.setOpcode(INVOKESPECIAL); method.owner = replace(method.owner, patchName, clazzName); } else if (insn instanceof InvokeDynamicInsnNode) { InvokeDynamicInsnNode dynamic = (InvokeDynamicInsnNode) insn; String patchDesc = ASMHelper.getClassDesc(patchName), clazzDesc = ASMHelper.getClassDesc(clazzName); dynamic.desc = replace(dynamic.desc, patchDesc, clazzDesc); for (int i = 0; i < dynamic.bsmArgs.length; i++) if (dynamic.bsmArgs[i] instanceof Handle) { Handle handle = (Handle) dynamic.bsmArgs[i]; dynamic.bsmArgs[i] = new Handle(handle.getTag(), replace(handle.getOwner(), patchName, clazzName), handle.getName(), replace(handle.getDesc(), patchDesc, clazzDesc), handle.isInterface()); } } else if (insn instanceof FrameNode) { FrameNode frame = (FrameNode) insn; if (frame.local != null) frame.local.replaceAll((o -> o instanceof String ? replace((String) o, patchName, clazzName) : o)); if (frame.stack != null) frame.stack.replaceAll((o -> o instanceof String ? replace((String) o, patchName, clazzName) : o)); } } }
@Override public void handle(AbstractInsnNode node) throws IncorrectNodeException { super.handle(node); LOG.debug(logNode(node)); checkType(node, FrameNode.class); mState.setFrameLabel(mState.getCurrentLabel()); }
@Override public final void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { FrameNode node = new FrameNode(type, nLocal, local == null ? null : convertValues(local), nStack, stack == null ? null : convertValues(stack)); instructions.add(node); addFrame(node); }
private static boolean isNextFrameNode(AbstractInsnNode node) { for (AbstractInsnNode next = node.getNext(); next != null && next.getOpcode() == -1; next = next.getNext()) { if (next instanceof FrameNode) { return true; } } return false; }
@Override public void transform(byte[] bytes, ClassNode cn) { //////////////////////////////////////////////////////////////// MethodNode method = this.findMethod(cn, "sendClickBlockToController", "func_147115_a"); InsnList code = method.instructions; code.clear(); LabelNode l0 = new LabelNode(); code.add(l0); code.add(new LineNumberNode(1460, l0)); code.add(new VarInsnNode(Opcodes.ILOAD, 1)); LabelNode l1 = new LabelNode(); code.add(new JumpInsnNode(Opcodes.IFNE, l1)); LabelNode l2 = new LabelNode(); code.add(l2); code.add(new LineNumberNode(1462, l2)); code.add(new VarInsnNode(Opcodes.ALOAD, 0)); code.add(new InsnNode(Opcodes.ICONST_0)); code.add(leftClickCounter.putField()); code.add(l1); code.add(new LineNumberNode(1484, l1)); code.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null)); code.add(new InsnNode(Opcodes.RETURN)); method.maxStack = 2; method.maxLocals = 2; //////////////////////////////////////////////////////////////// }
public CodeBlock visitFrame(final int opcode, final int nrLocals, final Object[] localTypes, final int nrStackElements, final Object[] stackElements) { instructionList.add(new FrameNode(opcode, nrLocals, localTypes, nrStackElements, stackElements)); return this; }
public void retrieveTaintedArrayWithoutTags(String type) { //A Label isNull = new Label(); Label isDone = new Label(); FrameNode fn = getCurrentFrameNode(); super.visitInsn(DUP); if(!isIgnoreAllInstrumenting) super.visitInsn(TaintUtils.IGNORE_EVERYTHING); super.visitJumpInsn(IFNULL, isNull); if(!isIgnoreAllInstrumenting) super.visitInsn(TaintUtils.IGNORE_EVERYTHING); // System.out.println("unbox: " + onStack + " type passed is " + type); Class boxType = MultiDTaintedArray.getClassForComponentType(Type.getType(type).getElementType().getSort()); super.visitTypeInsn(CHECKCAST, Type.getInternalName(boxType)); Type arrayDesc = Type.getType(type); // System.out.println("Get tainted array from " + arrayDesc); super.visitFieldInsn(GETFIELD, Type.getInternalName(boxType), "val", type); FrameNode fn2 = getCurrentFrameNode(); super.visitJumpInsn(GOTO, isDone); super.visitLabel(isNull); acceptFn(fn); super.visitTypeInsn(CHECKCAST, type); super.visitLabel(isDone); acceptFn(fn2); }
FrameNode generateFrameNode(int type, int nLocal, Object[] local, int nStack, Object[] stack) { FrameNode ret = new FrameNode(type, nLocal, local, nStack, stack); ret.local = new ArrayList<Object>(); ret.stack= new ArrayList<Object>(); visitFrameTypes(nLocal, local, ret.local); visitFrameTypes(nStack, stack, ret.stack); return ret; }
@Override public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { if (DEBUG) System.out.println("Rewriting " + curLabel + " OUT to " + analyzer.stack); outFrames.set(curLabel - 1, new FrameNode(0, analyzer.locals.size(), analyzer.locals.toArray(), analyzer.stack.size(), analyzer.stack.toArray())); super.visitTableSwitchInsn(min, max, dflt, labels); }
@Override public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { if (DEBUG) System.out.println("Rewriting " + curLabel + " OUT to " + analyzer.stack); outFrames.set(curLabel - 1, new FrameNode(0, analyzer.locals.size(), analyzer.locals.toArray(), analyzer.stack.size(), analyzer.stack.toArray())); super.visitLookupSwitchInsn(dflt, keys, labels); }
@Override public void visitInsn(int opcode) { if (opcode == Opcodes.ATHROW) { if (DEBUG) System.out.println("Rewriting " + curLabel + " OUT to " + analyzer.stack); if (analyzer.locals != null && analyzer.stack != null) outFrames.set(curLabel - 1, new FrameNode(0, analyzer.locals.size(), analyzer.locals.toArray(), analyzer.stack.size(), analyzer.stack.toArray())); } super.visitInsn(opcode); }
@Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { Type t = Type.getType(desc); if(t.getSort() == Type.ARRAY && t.getDimensions() > 1 && t.getElementType().getSort() != Type.OBJECT) desc = MultiDTaintedArray.getTypeForType(t).getDescriptor(); switch (opcode) { case Opcodes.GETFIELD: case Opcodes.GETSTATIC: super.visitFieldInsn(opcode, owner, name, desc); break; case Opcodes.PUTFIELD: case Opcodes.PUTSTATIC: if (t.getSort() == Type.ARRAY && t.getDimensions() == 1 && t.getElementType().getSort() != Type.OBJECT) { //1d prim array - need to make sure that there is some taint here FrameNode fn = getCurrentFrameNode(); fn.type = Opcodes.F_NEW; super.visitInsn(Opcodes.DUP); Label ok = new Label(); super.visitJumpInsn(IFNULL, ok); if (opcode == Opcodes.PUTFIELD) { //O A super.visitInsn(DUP2); //O A O A } else super.visitInsn(Opcodes.DUP); super.visitInsn(Opcodes.ARRAYLENGTH); if (!Configuration.MULTI_TAINTING) super.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_INT); else super.visitTypeInsn(Opcodes.ANEWARRAY, Configuration.TAINT_TAG_INTERNAL_NAME); super.visitFieldInsn(opcode, owner, name + TaintUtils.TAINT_FIELD, Configuration.TAINT_TAG_ARRAYDESC); super.visitLabel(ok); if (!skipFrames) fn.accept(this); } super.visitFieldInsn(opcode, owner, name, desc); break; } }
public boolean search() { for (AbstractInsnNode ain : insns.toArray()) { if (ain instanceof LineNumberNode || ain instanceof FrameNode) continue; if (pattern.accept(ain)) { matches.add(pattern.getLastMatch()); pattern.resetMatch(); } } return size() != 0; }
private FrameNode findOnlyFrameNode() { FrameNode f = null; for (int i = start; i != end; ++i) { AbstractInsnNode insn = methodNode.instructions.get(i); if (insn instanceof FrameNode) { assert f == null : f + " " +insn; f = (FrameNode)insn; } } return f; }
private void addLabelIfNecessary(final AbstractInsnNode insn) { AbstractInsnNode next = insn.getNext(); while (next != null) { if (next instanceof LabelNode && this.jumpTargetLabels.contains(next)) return; if (next instanceof FrameNode || next instanceof LineNumberNode) next = next.getNext(); else break; } traceLabel(null, InstructionType.SAFE); }
private boolean followedByJumpLabel(final ListIterator<AbstractInsnNode> iterator) { if (!iterator.hasNext()) return false; final AbstractInsnNode nextInsn = iterator.next(); iterator.previous(); for (AbstractInsnNode insn = nextInsn; insn != null; insn = insn.getNext()) { if (insn instanceof LabelNode && this.jumpTargetLabels.contains(insn)) return true; if (!(insn instanceof FrameNode || insn instanceof LineNumberNode)) break; } return false; }
public StackFrame(FrameNode node, LabelNode start, LabelNode end){ this.node = node; if (this.node.local == null) this.node.local = new ArrayList(); this.start = start; this.end = end; this.variables = new HashMap<Integer, LocalVariable>(); }
public static FrameNode frameSame() { return new FrameNode(F_SAME, 0, null, 0, null); }
public static FrameNode frameSame1(Class clazz) { return new FrameNode(F_SAME1, 0, null, 1, new Object[]{Type.getInternalName(clazz)}); }
public static FrameNode frameSame1(Class clazz) { return new FrameNode(F_SAME1, 0, null, 1, new Object[] { Type.getInternalName(clazz) }); }
static FrameNode getDefaultFrameNode() { return new FrameNode(F_SAME, 0, null, 0, null); }
/** * Represents this instruction as a string, for debugging purposes * * @param includeAdjacent whether it should include a display of * adjacent nodes as well * @return a string representation */ @NonNull public String toString(boolean includeAdjacent) { StringBuilder sb = new StringBuilder(100); sb.append(getId(instruction)); sb.append(':'); if (instruction instanceof LabelNode) { //LabelNode l = (LabelNode) instruction; //sb.append('L' + l.getLabel().getOffset() + ":"); //sb.append('L' + l.getLabel().info + ":"); sb.append("LABEL"); } else if (instruction instanceof LineNumberNode) { sb.append("LINENUMBER ").append(((LineNumberNode)instruction).line); } else if (instruction instanceof FrameNode) { sb.append("FRAME"); } else { int opcode = instruction.getOpcode(); String opcodeName = getOpcodeName(opcode); sb.append(opcodeName); if (instruction.getType() == AbstractInsnNode.METHOD_INSN) { sb.append('(').append(((MethodInsnNode)instruction).name).append(')'); } } if (includeAdjacent) { if (successors != null && !successors.isEmpty()) { sb.append(" Next:"); for (Node successor : successors) { sb.append(' '); sb.append(successor.toString(false)); } } if (exceptions != null && !exceptions.isEmpty()) { sb.append(" Exceptions:"); for (Node exception : exceptions) { sb.append(' '); sb.append(exception.toString(false)); } } sb.append('\n'); } return sb.toString(); }
@Override public void transform(String className, ClassNode node) { for (MethodNode method : node.methods) { if (method.name.equals(PLACE_ITEM.getEnvName()) && method.desc.equals(PLACE_ITEM.getDesc())) { boolean inserted = false; for (ListIterator<AbstractInsnNode> iterator = method.instructions.iterator(); iterator.hasNext();) { AbstractInsnNode insn = iterator.next(); if (insn.getNext() instanceof VarInsnNode && insn.getNext().getNext() instanceof VarInsnNode && insn.getNext().getNext().getNext() instanceof MethodInsnNode) { VarInsnNode next1 = (VarInsnNode) insn.getNext(); VarInsnNode next2 = (VarInsnNode) next1.getNext(); MethodInsnNode next3 = (MethodInsnNode) next2.getNext(); if (next1.getOpcode() == Opcodes.ALOAD && next1.var == 0 && next2.getOpcode() == Opcodes.ILOAD && next2.var == 14 && next3.getOpcode() == Opcodes.INVOKEVIRTUAL && next3.owner.equals(setCount.getOwnerInternalName()) && next3.name.equals(setCount.getEnvName()) && next3.desc.equals(setCount.getDesc())) { int varIndex = method.maxLocals; method.maxLocals++; InsnList postEvent = new InsnList(); LabelNode label = new LabelNode(new Label()); postEvent.add(new TypeInsnNode(Opcodes.NEW, CHANGE_SIZE_EVENT.getInternalName())); postEvent.add(new InsnNode(Opcodes.DUP)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 1)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 0)); postEvent.add(new VarInsnNode(Opcodes.ILOAD, 10)); postEvent.add(new VarInsnNode(Opcodes.ILOAD, 14)); postEvent.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, CHANGE_SIZE_EVENT_INIT.getOwnerInternalName(), CHANGE_SIZE_EVENT_INIT.getEnvName(), CHANGE_SIZE_EVENT_INIT.getDesc(), false)); postEvent.add(new VarInsnNode(Opcodes.ASTORE, varIndex)); postEvent.add(new FieldInsnNode(Opcodes.GETSTATIC, EVENTHANDLER_CHANGE_SIZE.getOwnerInternalName(), EVENTHANDLER_CHANGE_SIZE.getEnvName(), EVENTHANDLER_CHANGE_SIZE.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ALOAD, varIndex)); postEvent.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, POST.getOwnerInternalName(), POST.getEnvName(), POST.getDesc(), false)); postEvent.add(new JumpInsnNode(Opcodes.IFEQ, label)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, varIndex)); postEvent.add(new FieldInsnNode(Opcodes.GETFIELD, NEW_SIZE.getOwnerInternalName(), NEW_SIZE.getEnvName(), NEW_SIZE.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ISTORE, 14)); postEvent.add(label); postEvent.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null)); method.instructions.insert(insn, postEvent); inserted = true; break; } } } if (inserted) break; } } }
private static boolean isInstruction(final AbstractInsnNode ins) { return !((ins instanceof LabelNode) || (ins instanceof FrameNode)); }
private static FrameNode newFrameNode(Object[] locals, Object[] stack) { Object[] locals1 = convertValues(locals); Object[] stack1 = convertValues(stack); return new FrameNode(F_NEW, locals1.length, locals1, stack1.length, stack1); }
void replaceObjectInitialization( final MethodNode methodNode, final Frame<BasicValue>[] frames, final Set<AbstractInsnNode> objectCreationNodes) { int originalLocals = methodNode.maxLocals; final Set<AbstractInsnNode> uninitializedObjects = objectCreationNodes != null ? objectCreationNodes : Stream.of(methodNode.instructions.toArray()) .filter(new Predicate<AbstractInsnNode>() { @Override public boolean test(final AbstractInsnNode i) { return i.getOpcode() == NEW; } }) .collect(Collectors.toSet()); // since we can't store uninitialized objects they have to be removed or replaced. // this works for bytecodes where the initialization is implemented like: // NEW T // DUP // ... // T.<init>(..)V // and the stack before <init> is: {... T' T' args} // and the stack after <init> is: {... T} // this conforms all cases of java derived bytecode that I'm aware of. // but it might not be always true. // replace frameNodes and constructor calls int index = 0; for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; index++, insnNode = insnNode.getNext()) { if (insnNode instanceof FrameNode) { FrameNode frameNode = (FrameNode) insnNode; frameNode.stack = replaceUninitializedFrameValues(uninitializedObjects, frameNode.stack); frameNode.local = replaceUninitializedFrameValues(uninitializedObjects, frameNode.local); } else if (insnNode.getOpcode() == INVOKESPECIAL) { MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; if (methodInsnNode.name.equals("<init>")) { insnNode = replaceConstructorCall(methodNode, frames[index], uninitializedObjects, originalLocals, methodInsnNode); } } } // replace new calls for (AbstractInsnNode insnNode = methodNode.instructions.getFirst(); insnNode != null; insnNode = insnNode.getNext()) { if (insnNode.getOpcode() == NEW && (uninitializedObjects.contains(insnNode))) { InsnNode newInsn = new InsnNode(ACONST_NULL); methodNode.instructions.insertBefore(insnNode, newInsn); methodNode.instructions.remove(insnNode); insnNode = newInsn; } } }
protected void init(String owner, MethodNode m) throws AnalyzerException { final Frame[] frames = getFrames(); // populates frames from frame nodes AbstractInsnNode insnNode = m.instructions.getFirst(); FrameAnalyzer.TypeInterpreter interpreter = FrameAnalyzer.TypeInterpreter.instance; Frame lastFrame = frames[0]; for (int insnIndex = 0; insnNode != null; insnNode = insnNode.getNext(), insnIndex++) { if (insnNode instanceof FrameNode) { FrameNode frameNode = (FrameNode) insnNode; final int frameType = frameNode.type; if (frameType == F_NEW || frameType == F_FULL) { ExtendedFrame frame = (ExtendedFrame) newFrame(lastFrame); frame.force = true; frames[insnIndex] = frame; int iLocal_w = 0; if (frameNode.local != null && frameNode.local.size() > 0) { for (int j = 0; j < frameNode.local.size(); j++) { BasicValue value = convertFrameNodeType(frameNode.local.get(j)); frame.setLocal(iLocal_w, value); iLocal_w += value.getSize(); } } BasicValue nullValue = interpreter.newValue(null); while (iLocal_w < m.maxLocals) { frame.setLocal(iLocal_w++, nullValue); } frame.clearStack(); if (frameNode.stack != null && frameNode.stack.size() > 0) { for (int j = 0; j < frameNode.stack.size(); j++) { frame.push(convertFrameNodeType(frameNode.stack.get(j))); } } lastFrame = frame; } } } }
public static boolean instructionsEqual(AbstractInsnNode insn1, AbstractInsnNode insn2) { if (insn1 == insn2) { return true; } if (insn1 == null || insn2 == null || insn1.type() != insn2.type() || insn1.opcode() != insn2.opcode()) { return false; } int size; switch (insn1.type()) { case INSN: return true; case INT_INSN: IntInsnNode iin1 = (IntInsnNode) insn1, iin2 = (IntInsnNode) insn2; return iin1.operand == iin2.operand; case VAR_INSN: VarInsnNode vin1 = (VarInsnNode) insn1, vin2 = (VarInsnNode) insn2; return vin1.var == vin2.var; case TYPE_INSN: TypeInsnNode tin1 = (TypeInsnNode) insn1, tin2 = (TypeInsnNode) insn2; return tin1.desc.equals(tin2.desc); case FIELD_INSN: FieldInsnNode fin1 = (FieldInsnNode) insn1, fin2 = (FieldInsnNode) insn2; return fin1.desc.equals(fin2.desc) && fin1.name.equals(fin2.name) && fin1.owner.equals(fin2.owner); case METHOD_INSN: MethodInsnNode min1 = (MethodInsnNode) insn1, min2 = (MethodInsnNode) insn2; return min1.desc.equals(min2.desc) && min1.name.equals(min2.name) && min1.owner.equals(min2.owner); case INVOKE_DYNAMIC_INSN: InvokeDynamicInsnNode idin1 = (InvokeDynamicInsnNode) insn1, idin2 = (InvokeDynamicInsnNode) insn2; return idin1.bsm.equals(idin2.bsm) && Arrays.equals(idin1.bsmArgs, idin2.bsmArgs) && idin1.desc.equals(idin2.desc) && idin1.name.equals(idin2.name); case JUMP_INSN: JumpInsnNode jin1 = (JumpInsnNode) insn1, jin2 = (JumpInsnNode) insn2; return instructionsEqual(jin1.label, jin2.label); case LABEL: Label label1 = ((LabelNode) insn1).getLabel(), label2 = ((LabelNode) insn2).getLabel(); return label1 == null ? label2 == null : label1.info == null ? label2.info == null : label1.info.equals(label2.info); case LDC_INSN: LdcInsnNode lin1 = (LdcInsnNode) insn1, lin2 = (LdcInsnNode) insn2; return lin1.cst.equals(lin2.cst); case IINC_INSN: IincInsnNode iiin1 = (IincInsnNode) insn1, iiin2 = (IincInsnNode) insn2; return iiin1.incr == iiin2.incr && iiin1.var == iiin2.var; case TABLESWITCH_INSN: TableSwitchInsnNode tsin1 = (TableSwitchInsnNode) insn1, tsin2 = (TableSwitchInsnNode) insn2; size = tsin1.labels.size(); if (size != tsin2.labels.size()) { return false; } for (int i = 0; i < size; i++) { if (!instructionsEqual(tsin1.labels.get(i), tsin2.labels.get(i))) { return false; } } return instructionsEqual(tsin1.dflt, tsin2.dflt) && tsin1.max == tsin2.max && tsin1.min == tsin2.min; case LOOKUPSWITCH_INSN: LookupSwitchInsnNode lsin1 = (LookupSwitchInsnNode) insn1, lsin2 = (LookupSwitchInsnNode) insn2; size = lsin1.labels.size(); if (size != lsin2.labels.size()) { return false; } for (int i = 0; i < size; i++) { if (!instructionsEqual(lsin1.labels.get(i), lsin2.labels.get(i))) { return false; } } return instructionsEqual(lsin1.dflt, lsin2.dflt) && lsin1.keys.equals(lsin2.keys); case MULTIANEWARRAY_INSN: MultiANewArrayInsnNode manain1 = (MultiANewArrayInsnNode) insn1, manain2 = (MultiANewArrayInsnNode) insn2; return manain1.desc.equals(manain2.desc) && manain1.dims == manain2.dims; case FRAME: FrameNode fn1 = (FrameNode) insn1, fn2 = (FrameNode) insn2; return fn1.local.equals(fn2.local) && fn1.stack.equals(fn2.stack); case LINE: LineNumberNode lnn1 = (LineNumberNode) insn1, lnn2 = (LineNumberNode) insn2; return lnn1.line == lnn2.line && instructionsEqual(lnn1.start, lnn2.start); } return false; }
public void testClassRemapper() throws Exception { Map<String, String> map = new HashMap<String, String>(); map.put("Boo", "B1"); map.put("Coo", "C1"); map.put("Doo", "D1"); Remapper remapper = new SimpleRemapper(map); ClassNode cn = new ClassNode(); dump(new ClassRemapper(cn, remapper)); assertEquals("D1", cn.name); assertEquals("B1", cn.superName); assertEquals(Arrays.asList(new String[] { "I", "I", "C1", "J", "B1" }), cn.interfaces); assertEquals("LB1;", field(cn, 0).desc); assertEquals("[LB1;", field(cn, 1).desc); assertEquals("D1", innerClass(cn, 0).name); assertEquals("B1", innerClass(cn, 0).outerName); // assertEquals("Doo", innerClass(cn, 0).innerName); assertEquals("B1", cn.outerClass); assertEquals("([[LB1;LC1;LD1;)LC1;", cn.outerMethodDesc); MethodNode mn0 = cn.methods.get(0); ListIterator<AbstractInsnNode> it = mn0.instructions.iterator(); FieldInsnNode n0 = (FieldInsnNode) it.next(); assertEquals("D1", n0.owner); assertEquals("LB1;", n0.desc); assertEquals(Type.getType("LB1;"), ((LdcInsnNode) it.next()).cst); assertEquals(Type.getType("[LD1;"), ((LdcInsnNode) it.next()).cst); assertEquals(Type.getType("[I"), ((LdcInsnNode) it.next()).cst); assertEquals(Type.getType("J"), ((LdcInsnNode) it.next()).cst); assertEquals("B1", ((TypeInsnNode) it.next()).desc); assertEquals("[LD1;", ((TypeInsnNode) it.next()).desc); assertEquals("[I", ((TypeInsnNode) it.next()).desc); assertEquals("J", ((TypeInsnNode) it.next()).desc); MultiANewArrayInsnNode n3 = (MultiANewArrayInsnNode) it.next(); assertEquals("[[LB1;", n3.desc); MethodInsnNode n4 = (MethodInsnNode) it.next(); assertEquals("D1", n4.owner); assertEquals("([[LB1;LC1;LD1;)LC1;", n4.desc); FrameNode fn0 = (FrameNode) it.next(); assertEquals(Collections.EMPTY_LIST, fn0.local); assertEquals(Collections.EMPTY_LIST, fn0.stack); assertEquals(Arrays.asList(new Object[] { "B1", "C1", "D1" }), ((FrameNode) it.next()).local); assertEquals( Arrays.asList(new Object[] { Opcodes.INTEGER, "C1", Opcodes.INTEGER, "D1" }), ((FrameNode) it.next()).local); assertEquals(Arrays.asList(new Object[] { Opcodes.INTEGER, Opcodes.INTEGER }), ((FrameNode) it.next()).local); // assertEquals(Collections.EMPTY_LIST, fn0.stack); TryCatchBlockNode tryCatchBlockNode = mn0.tryCatchBlocks.get(0); assertEquals("C1", tryCatchBlockNode.type); MethodNode mn1 = cn.methods.get(1); assertEquals("([[LB1;LC1;LD1;)V", mn1.desc); assertEquals(Arrays.asList(new String[] { "I", "J" }), mn1.exceptions); }