Example usage for org.objectweb.asm MethodVisitor visitLabel

List of usage examples for org.objectweb.asm MethodVisitor visitLabel

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitLabel.

Prototype

public void visitLabel(final Label label) 

Source Link

Document

Visits a label.

Usage

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 &lt;stateVar&gt;
 *          
 *          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);
        }
    }
}