List of usage examples for org.objectweb.asm MethodVisitor visitLabel
public void visitLabel(final Label label)
From source file:jtaint.StringAdapter.java
License:Apache License
/** Add a new constructor to a create a (partially or fully) tainted * String. Equivalent to the following Java code: * * public String(String original, Taint t) { * super();//from www . jav a 2s . c om * this.count = original.count; * * if (!t.isTainted()) { * this.offset = original.offset; * this.value = original.value; * this.tainted = original.tainted; * return * } * * this.offset = 0; * this.value = jtaint.StringUtil.taintToString(original, t) * if (this.value.length == this.count) * this.tainted = false; * else * this.tainted = true; * return; * The final check (if value.length == count) is true only when an error * occurs during the execution of taintToString */ private void addConstructor(ClassVisitor cv) { MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/String;Ljtaint/Taint;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); copyField(mv, "count", "I"); Label l0 = new Label(); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/Taint", "isTainted", "()Z"); mv.visitJumpInsn(IFNE, l0); /* Taint object is actually untainted, copy all fields and return */ copyField(mv, "offset", "I"); copyField(mv, "value", "[C"); copyField(mv, ByteCodeUtil.internalName("tainted"), "Z"); mv.visitInsn(RETURN); mv.visitLabel(l0); if (version == V1_6) mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitInsn(ICONST_0); mv.visitFieldInsn(PUTFIELD, className, "offset", "I"); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKESTATIC, "jtaint/StringUtil", "taintToString", "(Ljava/lang/String;Ljtaint/Taint;)[C"); mv.visitInsn(DUP_X1); mv.visitFieldInsn(PUTFIELD, className, "value", "[C"); mv.visitInsn(ARRAYLENGTH); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, className, "count", "I"); Label l1 = new Label(); mv.visitJumpInsn(IF_ICMPEQ, l1); mv.visitVarInsn(ALOAD, 0); mv.visitInsn(ICONST_1); mv.visitFieldInsn(PUTFIELD, className, ByteCodeUtil.internalName("tainted"), "Z"); mv.visitInsn(RETURN); mv.visitLabel(l1); if (version == V1_6) mv.visitFrame(F_SAME, 0, null, 0, null); mv.visitVarInsn(ALOAD, 0); mv.visitInsn(ICONST_0); mv.visitFieldInsn(PUTFIELD, className, ByteCodeUtil.internalName("tainted"), "Z"); mv.visitInsn(RETURN); mv.visitMaxs(3, 3); mv.visitEnd(); }
From source file:jtaint.XssAdapter.java
License:Apache License
private void buildWriteIntWrapper(final MethodVisitor mv, final String methodName, final String desc) { new XssLockBuilder(mv, version, className, methodName, desc) { public void onUnlocked() { mv.visitVarInsn(ALOAD, 0);//w ww.j a v a 2 s . co m mv.visitMethodInsn(INVOKEVIRTUAL, className, ByteCodeUtil.internalName("getHtmlValidator"), "()Ljtaint/HtmlValidator;"); if ("javax/servlet/ServletOutputStream".equals(className)) { mv.visitVarInsn(ILOAD, 1); mv.visitInsn(I2B); mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "write", "(B)V"); } else if ("java/io/PrintWriter".equals(className)) { mv.visitVarInsn(ILOAD, 1); mv.visitInsn(I2C); mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "print", "(C)V"); } else { /* Runtime check required */ Label l0 = new Label(); Label l1 = new Label(); mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(INSTANCEOF, "java/io/PrintWriter"); mv.visitJumpInsn(IFNE, l1); /* If-branch, we're a ServletOutputStream. */ mv.visitVarInsn(ILOAD, 1); mv.visitInsn(I2B); mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "write", "(B)V"); mv.visitJumpInsn(GOTO, l0); /* Else-branch, we're a PrintWriter */ mv.visitLabel(l1); if (version == V1_6) mv.visitFrame(F_SAME1, 0, null, 1, new Object[] { "jtaint/HtmlValidator" }); mv.visitVarInsn(ILOAD, 1); mv.visitInsn(I2C); mv.visitMethodInsn(INVOKEVIRTUAL, "jtaint/HtmlValidator", "print", "(C)V"); mv.visitLabel(l0); if (version == V1_6) { mv.visitFrame(F_SAME, 0, null, 0, null); /* We can't end on a visitFrame because * InstrumentationLockAdapter performs a visitFrame * after this method completes. Two consecutive * visitFrames cause the Java 6 type checker to barf, * so just pad with a single NOP. */ mv.visitInsn(NOP); } } } }.build(); }
From source file:kilim.analysis.CallWeaver.java
License:Open Source License
void genCall(MethodVisitor mv) { mv.visitLabel(callLabel); loadVar(mv, TOBJECT, methodWeaver.getFiberVar()); mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "down", "()" + D_FIBER); MethodInsnNode mi = getMethodInsn(); if (mi.desc.indexOf(fiberArg) == -1) { // Don't add another fiberarg if it already has one. It'll already // have one if we have copied jsr instructions and modified the // same instruction node earlier. mi.desc = mi.desc.replace(")", fiberArg); }//from w ww .j a v a 2s. com mi.accept(mv); }
From source file:kilim.analysis.CallWeaver.java
License:Open Source License
/** * After the pausable method call is over, we have four possibilities. The * called method yielded, or it returned normally. Orthogonally, we have * saved state or not. fiber.up() returns the combined status * /*w w w . j a v a2 s. co m*/ ? * <pre> * * switch (fiber.up()) { * default: * 0: goto RESUME; // Not yielding , no State -- resume normal operations * 1: goto RESTORE; // Not yielding, has State -- restore state before resuming * 2: goto SAVE; // Yielding, no state -- save state before unwinding stack * 3: goto UNWIND // Yielding, has state -- nothing to do but unwind. * } * SAVE: * ... * xRETURN * UNWIND: * ... * xRETURN * RESTORE: * ... * // fall through to RESUME * RESUME: * ... original code * </pre> * * @param mv * */ void genPostCall(MethodVisitor mv) { loadVar(mv, TOBJECT, methodWeaver.getFiberVar()); mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "up", "()I"); Label restoreLabel = new Label(); Label saveLabel = new Label(); Label unwindLabel = new Label(); Label[] labels = new Label[] { resumeLabel, restoreLabel, saveLabel, unwindLabel }; mv.visitTableSwitchInsn(0, 3, resumeLabel, labels); genSave(mv, saveLabel); genUnwind(mv, unwindLabel); genRestore(mv, restoreLabel); mv.visitLabel(resumeLabel); }
From source file:kilim.analysis.CallWeaver.java
License:Open Source License
/** * Code for the case where we are yielding, and we have state built up from * a previous call. There's nothing meaningful to do except keep the * verifier happy. Pop the bottom stack, then return a dummy return value * (if this method -- note: not the called method -- returns a value) * // ww w . ja v a2 s. c om * @param mv */ private void genUnwind(MethodVisitor mv, Label unwindLabel) { mv.visitLabel(unwindLabel); // After the call returns, the stack would be left with numBottom plus // return value // pop callee's dummy return value first String rdesc = getReturnType(); if (rdesc != D_VOID) { mv.visitInsn(TypeDesc.isDoubleWord(rdesc) ? POP2 : POP); } // pop numbottom int i = getNumBottom() - 1; // the numBottom'th element Frame f = bb.startFrame; for (; i >= 0; i--) { mv.visitInsn(f.getStack(i).isCategory1() ? POP : POP2); } // Now for the return value of this (the calling) method rdesc = TypeDesc.getReturnTypeDesc(bb.flow.desc); if (rdesc != D_VOID) { // ICONST_0; IRETURN or ACONST_NULL; ARETURN etc. int vmt = VMType.toVmType(rdesc); mv.visitInsn(VMType.constInsn[vmt]); mv.visitInsn(VMType.retInsn[vmt]); } else { mv.visitInsn(RETURN); } }
From source file:kilim.analysis.CallWeaver.java
License:Open Source License
/** * Yielding, but state hasn't been captured yet. We create a state object * and save each object in valInfoList in its corresponding field. * /*from w ww . j a v a2 s. c o m*/ * Note that we save each stack item into a scratch register before loading * it into a field. The reason is that we need to get the State ref under * the stack item before we can do a putfield. The alternative is to load * the State item, then do a swap or a dup_x2;pop (depending on the value's * category). We'll go with the earlier approach because stack manipulations * don't seem to perform as well in the current crop of JVMs. * * @param mv */ private void genSave(MethodVisitor mv, Label saveLabel) { mv.visitLabel(saveLabel); Frame f = bb.startFrame; // pop return value if any. String retType = getReturnType(); if (retType != D_VOID) { // Yielding, so the return value from the called // function is a dummy value mv.visitInsn(TypeDesc.isDoubleWord(retType) ? POP2 : POP); } /* * Instantiate state class. Call one of new xxxState(this, pc, fiber), * or new xxxState(pc, fiber) depending whether this method is static or * not. Note that are not referring to the called method. * * pc, "the program counter" is merely the index of the call weaver in * the method weaver's list. This allows us to do a switch in the * method's entry. */ mv.visitTypeInsn(NEW, stateClassName); mv.visitInsn(DUP); // // call constructor mv.visitMethodInsn(INVOKESPECIAL, stateClassName, "<init>", "()V"); // save state in register int stateVar = allocVar(1); storeVar(mv, TOBJECT, stateVar); // state.self = this if the current executing method isn't static if (!bb.flow.isStatic()) { loadVar(mv, TOBJECT, stateVar); mv.visitInsn(ALOAD_0); // for state.self == this mv.visitFieldInsn(PUTFIELD, STATE_CLASS, "self", D_OBJECT); } int pc = methodWeaver.getPC(this); loadVar(mv, TOBJECT, stateVar); // state.pc if (pc < 6) { mv.visitInsn(ICONST_0 + pc); } else { mv.visitIntInsn(BIPUSH, pc); } mv.visitFieldInsn(PUTFIELD, STATE_CLASS, "pc", D_INT); // First save bottom stack into state int i = getNumBottom() - 1; for (; i >= 0; i--) { Value v = f.getStack(i); ValInfo vi = valInfoList.find(v); if (vi == null) { // it must be a constant or a duplicate, which is why we don't // have any information on it. just pop it. mv.visitInsn(v.category() == 2 ? POP2 : POP); } else { /** * xstore <scratchVar> ; send stack elem to some local var * aload <stateVar> ; load state * xload <scratchVar> ; get stack elem back * putfield ... ; state.fx = */ int var = allocVar(vi.val.category()); storeVar(mv, vi.vmt, var); loadVar(mv, VMType.TOBJECT, stateVar); loadVar(mv, vi.vmt, var); mv.visitFieldInsn(PUTFIELD, stateClassName, vi.fieldName, vi.fieldDesc()); releaseVar(var, vi.val.category()); } } // Now load up registers into fields int fieldNum = 0; for (ValInfo vi : valInfoList) { // Ignore values on stack if (vi.var == -1) continue; // aload state var // xload <var> loadVar(mv, TOBJECT, stateVar); loadVar(mv, vi.vmt, vi.var); mv.visitFieldInsn(PUTFIELD, stateClassName, vi.fieldName, vi.fieldDesc()); fieldNum++; } // Fiber.setState(state); loadVar(mv, TOBJECT, methodWeaver.getFiberVar()); loadVar(mv, TOBJECT, stateVar); mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "(" + D_STATE + ")V"); releaseVar(stateVar, 1); // Figure out the return type of the calling method and issue the // appropriate xRETURN instruction retType = TypeDesc.getReturnTypeDesc(bb.flow.desc); if (retType == D_VOID) { mv.visitInsn(RETURN); } else { int vmt = VMType.toVmType(retType); // ICONST_0, DCONST_0 etc. mv.visitInsn(VMType.constInsn[vmt]); // IRETURN, DRETURN, etc. mv.visitInsn(VMType.retInsn[vmt]); } }
From source file:kilim.analysis.CallWeaver.java
License:Open Source License
/** * Not yielding (resuming normally), but have stored state. We need to * restore from state before resuming. This is slightly more work than * saving state, because we have to restore constants and duplicates too. * <b>/*from w ww .ja va 2 s . c om*/ * * Note that the return value (if any) has a real value, which is why it * needs to be saved away before we can get access to the bottom elements to * pop them out. * * <pre> * If there is anything at the bottom save return value in scratch register * pop unnecessary bottom stuff. * * load fiber.curState * cast to specific state (if necessary) * astore in scratch <stateVar> * * for each value in frame.var * if val is constant or is in valInfoList, * push constant or load field (appropriately) * for each value in bottom stack * restore value similar to above * restore return value if any from scratch register * </pre> */ private void genRestore(MethodVisitor mv, Label restoreLabel) { mv.visitLabel(restoreLabel); Frame f = bb.startFrame; int numBottom = getNumBottom(); int retVar = -1; int retctype = -1; if (numBottom > 0) { // We have dummy values sitting in the stack. pop 'em. // But first, check if we have a real return value on top String retType = getReturnType(); if (retType != D_VOID) { // .. yep. save it to scratch register retctype = VMType.toVmType(retType); retVar = allocVar(VMType.category[retctype]); storeVar(mv, retctype, retVar); } // pop dummy values from stack bottom for (int i = numBottom - 1; i >= 0; i--) { Value v = f.getStack(i); int insn = v.isCategory1() ? POP : POP2; mv.visitInsn(insn); } } // Restore variables from state int stateVar = -1; if (valInfoList.size() > 0) { stateVar = allocVar(1); } genRestoreVars(mv, stateVar); // Now restore the bottom values in the stack from state for (int i = 0; i < numBottom; i++) { Value v = f.getStack(i); if (v.isConstant()) { loadConstant(mv, v); } else { ValInfo vi = valInfoList.find(v); if (vi.var == -1) { loadVar(mv, TOBJECT, stateVar); mv.visitFieldInsn(GETFIELD, stateClassName, vi.fieldName, vi.fieldDesc()); checkcast(mv, v); } else { // this stack value is a duplicate of a local var, which has // already been loaded and is of the right type loadVar(mv, vi.vmt, vi.var); } } } // restore the saved return value, if any // But we would have popped and saved the return value only // if there were any dummy values in the stack bottom to be // cleared out. If not, we wouldn't have bothered // popping the return value in the first place. if (numBottom > 0) { if (retVar != -1) { loadVar(mv, retctype, retVar); } } releaseVar(stateVar, 1); if (retctype != -1) { releaseVar(retVar, VMType.category[retctype]); } // Fall through to the resumeLabel in genNY_NS, so no goto required. }
From source file:kilim.analysis.CallWeaver.java
License:Open Source License
void genRestoreEx(MethodVisitor mv, Label restoreLabel) { mv.visitLabel(restoreLabel); int stateVar = -1; if (valInfoList.size() > 0) { stateVar = allocVar(1);// w w w. j a v a2 s . c om } genRestoreVars(mv, stateVar); releaseVar(stateVar, 1); }
From source file:kilim.analysis.MethodFlow.java
License:Open Source License
@Override /**//w w w .ja v a2 s . co m * Copied verbatim from MethodNode except for the instruction processing. * Unlike MethodNode, we don't keep LabelNodes inline, so we need to * do visitLabel ourselves. * * @param mv a method visitor. */ public void accept(final MethodVisitor mv) { // visits the method attributes int i, j, n; if (annotationDefault != null) { AnnotationVisitor av = mv.visitAnnotationDefault(); acceptAnnotation(av, null, annotationDefault); av.visitEnd(); } n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); for (i = 0; i < n; ++i) { AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i); an.accept(mv.visitAnnotation(an.desc, true)); } n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); for (i = 0; i < n; ++i) { AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i); an.accept(mv.visitAnnotation(an.desc, false)); } n = visibleParameterAnnotations == null ? 0 : visibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List<?> l = visibleParameterAnnotations[i]; if (l == null) { continue; } for (j = 0; j < l.size(); ++j) { AnnotationNode an = (AnnotationNode) l.get(j); an.accept(mv.visitParameterAnnotation(i, an.desc, true)); } } n = invisibleParameterAnnotations == null ? 0 : invisibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List<?> l = invisibleParameterAnnotations[i]; if (l == null) { continue; } for (j = 0; j < l.size(); ++j) { AnnotationNode an = (AnnotationNode) l.get(j); an.accept(mv.visitParameterAnnotation(i, an.desc, false)); } } n = attrs == null ? 0 : attrs.size(); for (i = 0; i < n; ++i) { mv.visitAttribute((Attribute) attrs.get(i)); } // visits the method's code if (instructions.size() > 0) { mv.visitCode(); // visits try catch blocks for (i = 0; i < tryCatchBlocks.size(); ++i) { ((TryCatchBlockNode) tryCatchBlocks.get(i)).accept(mv); } // visits instructions for (i = 0; i < instructions.size(); ++i) { Label l = getLabelAt(i); if (l != null) { mv.visitLabel(l); } ((AbstractInsnNode) instructions.get(i)).accept(mv); } Label l = getLabelAt(instructions.size()); if (l != null) { mv.visitLabel(l); } // visits local variables n = localVariables == null ? 0 : localVariables.size(); for (i = 0; i < n; ++i) { ((LocalVariableNode) localVariables.get(i)).accept(mv); } // visits line numbers /* TODO this was in ASM 2.3.3 but not 3.x or 4.0, find a substitute or remove n = lineNumbers == null ? 0 : lineNumbers.size(); for (i = 0; i < n; ++i) { ((LineNumberNode) lineNumbers.get(i)).accept(mv); } */ // visits maxs mv.visitMaxs(maxStack, maxLocals); } mv.visitEnd(); }
From source file:kilim.analysis.MethodWeaver.java
License:Open Source License
private void visitInstructions(MethodVisitor mv) { //TODO gen code for pausable JSRs genPrelude(mv);//from w w w . ja v a2 s . com MethodFlow mf = methodFlow; BasicBlock lastBB = null; for (BasicBlock bb : mf.getBasicBlocks()) { int from = bb.startPos; if (bb.isPausable() && bb.startFrame != null) { genPausableMethod(mv, bb); from = bb.startPos + 1; // first instruction is consumed } else if (bb.isCatchHandler()) { List<CallWeaver> cwList = getCallsUnderCatchBlock(bb); if (cwList != null) { genException(mv, bb, cwList); from = bb.startPos + 1; // first instruction is consumed } // else no different from any other block } int to = bb.endPos; for (int i = from; i <= to; i++) { Label l = mf.getLabelAt(i); if (l != null) { mv.visitLabel(l); } bb.getInstruction(i).accept(mv); } lastBB = bb; } if (lastBB != null) { Label l = methodFlow.getLabelAt(lastBB.endPos + 1); if (l != null) { mv.visitLabel(l); } } }