org.apache.bcel.generic.MethodGen

Here are the examples of the java api org.apache.bcel.generic.MethodGen taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

83 Examples 7

19 Source : RepeatedConditionals.java
with GNU Lesser General Public License v2.1
from spotbugs

private boolean compareCode(int first, int endOfFirstSegment, int second, int endOfSecondSegment, boolean oppositeChecks) {
    if (endOfFirstSegment - first != endOfSecondSegment - second) {
        return false;
    }
    MethodGen methodGen = null;
    try {
        methodGen = Global.getreplacedysisCache().getMethodreplacedysis(MethodGen.clreplaced, getMethodDescriptor());
    } catch (CheckedreplacedysisException e) {
    // Ignore
    }
    if (methodGen == null) {
        // MethodGen is absent for some reason: fallback to byte-to-byte comparison
        byte[] code = getCode().getCode();
        for (int i = first; i < endOfFirstSegment; i++) {
            if (code[i] != code[i - first + second]) {
                return false;
            }
        }
        return true;
    }
    InstructionHandle firstHandle = methodGen.getInstructionList().findHandle(first);
    InstructionHandle secondHandle = methodGen.getInstructionList().findHandle(second);
    while (true) {
        if (firstHandle == null || secondHandle == null) {
            return false;
        }
        if (firstHandle.getPosition() >= endOfFirstSegment) {
            return secondHandle.getPosition() >= endOfSecondSegment;
        }
        if (secondHandle.getPosition() >= endOfSecondSegment) {
            return firstHandle.getPosition() >= endOfFirstSegment;
        }
        Instruction firstInstruction = firstHandle.getInstruction();
        Instruction secondInstruction = secondHandle.getInstruction();
        if (firstInstruction instanceof BranchInstruction && secondInstruction instanceof BranchInstruction) {
            int firstOpcode = firstInstruction.getOpcode();
            int secondOpcode = secondInstruction.getOpcode();
            if (firstOpcode != secondOpcode) {
                return false;
            }
            int firstTarget = ((BranchInstruction) firstInstruction).getTarget().getPosition();
            int secondTarget = ((BranchInstruction) secondInstruction).getTarget().getPosition();
            if (firstTarget == second) {
                if (oppositeChecks || secondTarget <= endOfSecondSegment) {
                    return false;
                }
            } else {
                if (!((firstTarget >= first && firstTarget <= endOfFirstSegment && firstTarget - first == secondTarget - second) || firstTarget == secondTarget)) {
                    return false;
                }
            }
        } else {
            if (!firstInstruction.equals(secondInstruction)) {
                return false;
            }
        }
        firstHandle = firstHandle.getNext();
        secondHandle = secondHandle.getNext();
    }
}

19 Source : FindSqlInjection.java
with GNU Lesser General Public License v2.1
from spotbugs

private BugInstance generateBugInstance(JavaClreplaced javaClreplaced, MethodGen methodGen, InstructionHandle handle, StringAppendState stringAppendState, boolean isExecute) {
    int priority = LOW_PRIORITY;
    boolean sawSeriousTaint = false;
    if (stringAppendState.getSawAppend(handle)) {
        if (stringAppendState.getSawOpenQuote(handle) && stringAppendState.getSawCloseQuote(handle)) {
            priority = HIGH_PRIORITY;
        } else if (stringAppendState.getSawComma(handle)) {
            priority = NORMAL_PRIORITY;
        }
        if (!stringAppendState.getSawUnsafeAppend(handle)) {
            priority += 2;
        } else if (stringAppendState.getSawSeriousTaint(handle)) {
            priority--;
            sawSeriousTaint = true;
        } else if (!stringAppendState.getSawTaint(handle)) {
            priority++;
        }
    }
    String description;
    if (isExecute) {
        description = "SQL_NONCONSTANT_STRING_PreplacedED_TO_EXECUTE";
    } else {
        description = "SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING";
    }
    BugInstance bug = new BugInstance(this, description, priority);
    bug.addClreplacedAndMethod(methodGen, javaClreplaced.getSourceFileName());
    if (sawSeriousTaint) {
        bug.addString("non-constant SQL string involving HTTP taint");
    }
    return bug;
}

19 Source : MemberUtils.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Checks if the method could be a lambda. Notice this is a best-check,
 * since once compiled lambda methods are not univocally distinguishable.
 *
 * @param m The method to check if it's a lambda
 * @return True if this could be a lambda, false otherwise
 */
public static boolean couldBeLambda(final MethodGen m) {
    return m.isPrivate() && internalIsSynthetic(m);
}

19 Source : BugAccumulator.java
with GNU Lesser General Public License v2.1
from spotbugs

public void acreplacedulateBug(BugInstance bug, ClreplacedContext clreplacedContext, MethodGen methodGen, String sourceFile, Location location) {
    acreplacedulateBug(bug, SourceLineAnnotation.fromVisitedInstruction(clreplacedContext, methodGen, sourceFile, location.getHandle()));
}

19 Source : XFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

public static XMethod createXMethod(MethodGen methodGen) {
    String clreplacedName = methodGen.getClreplacedName();
    String methodName = methodGen.getName();
    String methodSig = methodGen.getSignature();
    int accessFlags = methodGen.getAccessFlags();
    return createXMethod(clreplacedName, methodName, methodSig, accessFlags);
}

19 Source : ValueNumberFrameModelingVisitor.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Visitor which models the effects of bytecode instructions on value numbers of
 * values in the operand stack frames.
 *
 * @see ValueNumber
 * @see ValueNumberFrame
 * @see ValueNumberreplacedysis
 * @author David Hovemeyer
 */
public clreplaced ValueNumberFrameModelingVisitor extends AbstractFrameModelingVisitor<ValueNumber, ValueNumberFrame> implements Debug, ValueNumberreplacedysisFeatures {

    /*
     * ----------------------------------------------------------------------
     * Fields
     * ----------------------------------------------------------------------
     */
    private final MethodGen methodGen;

    ValueNumberFactory factory;

    private final ValueNumberCache cache;

    private final LoadedFieldSet loadedFieldSet;

    private final HashMap<Object, ValueNumber> constantValueMap;

    private final HashMap<ValueNumber, String> stringConstantMap;

    private InstructionHandle handle;

    private static final ValueNumber[] EMPTY_INPUT_VALUE_LIST = new ValueNumber[0];

    /*
     * ----------------------------------------------------------------------
     * Public interface
     * ----------------------------------------------------------------------
     */
    /**
     * Constructor.
     *
     * @param methodGen
     *            the method being replacedyzed
     * @param factory
     *            factory for ValueNumbers for the method
     * @param cache
     *            cache of input/output transformations for each instruction
     * @param loadedFieldSet
     *            fields loaded/stored by each instruction and entire method
     * @param lookupFailureCallback
     *            callback to use to report clreplaced lookup failures
     */
    public ValueNumberFrameModelingVisitor(MethodGen methodGen, ValueNumberFactory factory, ValueNumberCache cache, LoadedFieldSet loadedFieldSet, RepositoryLookupFailureCallback lookupFailureCallback) {
        super(methodGen.getConstantPool());
        this.methodGen = methodGen;
        this.factory = factory;
        this.cache = cache;
        this.loadedFieldSet = loadedFieldSet;
        this.constantValueMap = new HashMap<>();
        this.stringConstantMap = new HashMap<>();
    }

    @Override
    public ValueNumber getDefaultValue() {
        return factory.createFreshValue();
    }

    /**
     * Set the instruction handle of the instruction currently being visited.
     * This must be called before the instruction accepts this visitor!
     */
    public void setHandle(InstructionHandle handle) {
        this.handle = handle;
    }

    /*
     * ----------------------------------------------------------------------
     * Instruction modeling
     * ----------------------------------------------------------------------
     */
    /**
     * Determine whether redundant load elimination should be performed for the
     * heap location referenced by the current instruction.
     *
     * @return true if we should do redundant load elimination for the current
     *         instruction, false if not
     */
    private boolean doRedundantLoadElimination() {
        if (!REDUNDANT_LOAD_ELIMINATION) {
            return false;
        }
        XField xfield = loadedFieldSet.getField(handle);
        if (xfield == null) {
            return false;
        }
        // TODO: support two-slot fields
        return !(xfield.getSignature().equals("D") || xfield.getSignature().equals("J"));
    }

    /**
     * Determine whether forward subsreplacedution should be performed for the heap
     * location referenced by the current instruction.
     *
     * @return true if we should do forward subsreplacedution for the current
     *         instruction, false if not
     */
    private boolean doForwardSubsreplacedution() {
        if (!REDUNDANT_LOAD_ELIMINATION) {
            return false;
        }
        XField xfield = loadedFieldSet.getField(handle);
        if (xfield == null) {
            return false;
        }
        if (xfield.getSignature().equals("D") || xfield.getSignature().equals("J")) {
            return false;
        }
        // Don't do forward subsreplacedution for fields that
        // are never read.
        return loadedFieldSet.isLoaded(xfield);
    }

    private void checkConsumedAndProducedValues(Instruction ins, ValueNumber[] consumedValueList, ValueNumber[] producedValueList) {
        int numConsumed = ins.consumeStack(getCPG());
        int numProduced = ins.produceStack(getCPG());
        if (numConsumed == Const.UNPREDICTABLE) {
            throw new InvalidBytecodeException("Unpredictable stack consumption for " + ins);
        }
        if (numProduced == Const.UNPREDICTABLE) {
            throw new InvalidBytecodeException("Unpredictable stack production for " + ins);
        }
        if (consumedValueList.length != numConsumed) {
            throw new IllegalStateException("Wrong number of values consumed for " + ins + ": expected " + numConsumed + ", got " + consumedValueList.length);
        }
        if (producedValueList.length != numProduced) {
            throw new IllegalStateException("Wrong number of values produced for " + ins + ": expected " + numProduced + ", got " + producedValueList.length);
        }
    }

    /**
     * This is the default instruction modeling method.
     */
    @Override
    public void modelNormalInstruction(Instruction ins, int numWordsConsumed, int numWordsProduced) {
        int flags = 0;
        if (ins instanceof InvokeInstruction) {
            flags = ValueNumber.RETURN_VALUE;
        } else if (ins instanceof ArrayInstruction) {
            flags = ValueNumber.ARRAY_VALUE;
        } else if (ins instanceof ConstantPushInstruction) {
            flags = ValueNumber.CONSTANT_VALUE;
        }
        // Get the input operands to this instruction.
        ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
        // See if we have the output operands in the cache.
        // If not, push default (fresh) values for the output,
        // and add them to the cache.
        ValueNumber[] outputValueList = getOutputValues(inputValueList, numWordsProduced, flags);
        if (VERIFY_INTEGRITY) {
            checkConsumedAndProducedValues(ins, inputValueList, outputValueList);
        }
        // Push output operands on stack.
        pushOutputValues(outputValueList);
    }

    @Override
    public void visitGETFIELD(GETFIELD obj) {
        XField xfield = Hierarchy.findXField(obj, getCPG());
        if (xfield != null) {
            if (xfield.isVolatile()) {
                getFrame().killAllLoads();
            }
            if (doRedundantLoadElimination()) {
                loadInstanceField(xfield, obj);
                return;
            }
        }
        handleNormalInstruction(obj);
    }

    @Override
    public void visitPUTFIELD(PUTFIELD obj) {
        if (doForwardSubsreplacedution()) {
            XField xfield = Hierarchy.findXField(obj, getCPG());
            if (xfield != null) {
                storeInstanceField(xfield, obj, false);
                return;
            }
        }
        handleNormalInstruction(obj);
    }

    @Override
    public void visitGETSTATIC(GETSTATIC obj) {
        ConstantPoolGen cpg = getCPG();
        String fieldName = obj.getName(cpg);
        String fieldSig = obj.getSignature(cpg);
        ValueNumberFrame frame = getFrame();
        if (RLE_DEBUG) {
            System.out.println("GETSTATIC of " + fieldName + " : " + fieldSig);
        }
        // Is this an access of a Clreplaced object?
        if (fieldName.startsWith("clreplaced$") && "Ljava/lang/Clreplaced;".equals(fieldSig)) {
            String clreplacedName = fieldName.substring("clreplaced$".length()).replace('$', '.');
            if (RLE_DEBUG) {
                System.out.println("[found load of clreplaced object " + clreplacedName + "]");
            }
            ValueNumber value = factory.getClreplacedObjectValue(clreplacedName);
            frame.pushValue(value);
            return;
        }
        XField xfield = Hierarchy.findXField(obj, getCPG());
        if (xfield != null) {
            if (xfield.isVolatile()) {
                getFrame().killAllLoads();
            }
            if (doRedundantLoadElimination()) {
                loadStaticField(xfield, obj);
                return;
            }
        }
        handleNormalInstruction(obj);
    }

    @Override
    public void visitPUTSTATIC(PUTSTATIC obj) {
        if (doForwardSubsreplacedution()) {
            XField xfield = Hierarchy.findXField(obj, getCPG());
            if (xfield != null) {
                storeStaticField(xfield, obj, false);
                return;
            }
        }
        handleNormalInstruction(obj);
    }

    @Override
    public void visitINVOKESTATIC(INVOKESTATIC obj) {
        if (REDUNDANT_LOAD_ELIMINATION) {
            ConstantPoolGen cpg = getCPG();
            String targetClreplacedName = obj.getClreplacedName(cpg);
            String methodName = obj.getName(cpg);
            String methodSig = obj.getSignature(cpg);
            if (("forName".equals(methodName) && "java.lang.Clreplaced".equals(targetClreplacedName) || "clreplaced$".equals(methodName)) && "(Ljava/lang/String;)Ljava/lang/Clreplaced;".equals(methodSig)) {
                // Access of a Clreplaced object
                ValueNumberFrame frame = getFrame();
                try {
                    ValueNumber arg = frame.getTopValue();
                    String clreplacedName = stringConstantMap.get(arg);
                    if (clreplacedName != null) {
                        frame.popValue();
                        if (RLE_DEBUG) {
                            System.out.println("[found access of clreplaced object " + clreplacedName + "]");
                        }
                        frame.pushValue(factory.getClreplacedObjectValue(clreplacedName));
                        return;
                    }
                } catch (DataflowreplacedysisException e) {
                    throw new InvalidBytecodeException("stack underflow", methodGen, handle, e);
                }
            } else if (Hierarchy.isInnerClreplacedAccess(obj, cpg)) {
                // Possible access of field via an inner-clreplaced access method
                XField xfield = loadedFieldSet.getField(handle);
                if (xfield != null) {
                    if (loadedFieldSet.instructionIsLoad(handle)) {
                        // Load via inner-clreplaced accessor
                        if (doRedundantLoadElimination()) {
                            if (xfield.isStatic()) {
                                loadStaticField(xfield, obj);
                            } else {
                                loadInstanceField(xfield, obj);
                            }
                            return;
                        }
                    } else {
                        // Store via inner-clreplaced accessor
                        if (doForwardSubsreplacedution()) {
                            // Some inner clreplaced access store methods
                            // return the value stored.
                            boolean pushValue = !methodSig.endsWith(")V");
                            if (xfield.isStatic()) {
                                storeStaticField(xfield, obj, pushValue);
                            } else {
                                storeInstanceField(xfield, obj, pushValue);
                            }
                            return;
                        }
                    }
                }
            }
        }
        handleNormalInstruction(obj);
    }

    private void killLoadsOfObjectsPreplaceded(INVOKEDYNAMIC ins) {
        try {
            int preplaceded = getNumWordsConsumed(ins);
            ValueNumber[] arguments = allocateValueNumberArray(preplaceded);
            getFrame().getTopStackWords(arguments);
            for (ValueNumber v : arguments) {
                getFrame().killAllLoadsOf(v);
            }
        } catch (DataflowreplacedysisException e) {
            replacedysisContext.logError("Error in killLoadsOfObjectsPreplaceded", e);
        }
    }

    private void killLoadsOfObjectsPreplaceded(InvokeInstruction ins) {
        try {
            XMethod called = Hierarchy2.findExactMethod(ins, methodGen.getConstantPool(), Hierarchy.ANY_METHOD);
            if (called != null) {
                NoSideEffectMethodsDatabase nse = Global.getreplacedysisCache().getOptionalDatabase(NoSideEffectMethodsDatabase.clreplaced);
                if (nse != null && !nse.is(called.getMethodDescriptor(), MethodSideEffectStatus.SE, MethodSideEffectStatus.OBJ)) {
                    return;
                }
            }
            FieldSummary fieldSummary = replacedysisContext.currentreplacedysisContext().getFieldSummary();
            Set<XField> touched = fieldSummary.getFieldsWritten(called);
            if (!touched.isEmpty()) {
                getFrame().killLoadsOf(touched);
            }
            int preplaceded = getNumWordsConsumed(ins);
            ValueNumber[] arguments = allocateValueNumberArray(preplaceded);
            getFrame().killLoadsWithSimilarName(ins.getClreplacedName(cpg), ins.getMethodName(cpg));
            getFrame().getTopStackWords(arguments);
            for (ValueNumber v : arguments) {
                getFrame().killAllLoadsOf(v);
            }
            // Too many false-positives for primitives without transitive FieldSummary replacedysis,
            // so currently we simply kill any writable primitive on any method call
            // TODO: implement transitive FieldSummary
            getFrame().killAllLoads(true);
        } catch (DataflowreplacedysisException e) {
            replacedysisContext.logError("Error in killLoadsOfObjectsPreplaceded", e);
        }
    }

    @Override
    public void visitMONITORENTER(MONITORENTER obj) {
        // Don't know what this sync invocation is doing.
        // Kill all loads.
        ValueNumber topValue = null;
        try {
            topValue = getFrame().getStackValue(0);
        } catch (DataflowreplacedysisException e) {
            replacedysisContext.logError("error handling monitor enter in value numbering", e);
        }
        getFrame().killAllLoadsExceptFor(topValue);
        handleNormalInstruction(obj);
    }

    public void visitInvokeOnException(Instruction obj) {
        if (!REDUNDANT_LOAD_ELIMINATION || !getFrame().hasAvailableLoads()) {
            return;
        }
        if (obj instanceof INVOKEDYNAMIC) {
            killLoadsOfObjectsPreplaceded((INVOKEDYNAMIC) obj);
            return;
        }
        InvokeInstruction inv = (InvokeInstruction) obj;
        if ((inv instanceof INVOKEINTERFACE || inv instanceof INVOKEVIRTUAL) && inv.getMethodName(cpg).toLowerCase().indexOf("lock") >= 0) {
            // Don't know what this method invocation is doing.
            // Kill all loads.
            getFrame().killAllLoads();
            return;
        }
        if (inv instanceof INVOKEVIRTUAL && "cast".equals(inv.getMethodName(cpg)) && "java.lang.Clreplaced".equals(inv.getClreplacedName(cpg))) {
            // No-op
            return;
        }
        if (inv instanceof INVOKESTATIC) {
            String methodName = inv.getName(cpg);
            if (("forName".equals(methodName) && "java.lang.Clreplaced".equals(inv.getClreplacedName(cpg)) || "clreplaced$".equals(methodName)) && "(Ljava/lang/String;)Ljava/lang/Clreplaced;".equals(inv.getSignature(cpg)) || (Hierarchy.isInnerClreplacedAccess((INVOKESTATIC) inv, cpg) && loadedFieldSet.getField(handle) != null)) {
                return;
            }
        }
        killLoadsOfObjectsPreplaceded(inv);
        if (inv instanceof INVOKESTATIC) {
            getFrame().killAllLoadsOf(null);
        }
    }

    @Override
    public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) {
        if ("cast".equals(obj.getMethodName(cpg)) && "java.lang.Clreplaced".equals(obj.getClreplacedName(cpg))) {
            // treat as no-op
            try {
                ValueNumberFrame frame = getFrame();
                ValueNumber resultType = frame.popValue();
                frame.popValue();
                frame.pushValue(resultType);
            } catch (DataflowreplacedysisException e) {
                replacedysisContext.logError("oops", e);
            }
            return;
        }
        handleNormalInstruction(obj);
    }

    @Override
    public void visitACONST_NULL(ACONST_NULL obj) {
        // Get the input operands to this instruction.
        ValueNumber[] inputValueList = popInputValues(0);
        // See if we have the output operands in the cache.
        // If not, push default (fresh) values for the output,
        // and add them to the cache.
        ValueNumber[] outputValueList = getOutputValues(inputValueList, 1, ValueNumber.CONSTANT_VALUE);
        if (VERIFY_INTEGRITY) {
            checkConsumedAndProducedValues(obj, inputValueList, outputValueList);
        }
        // Push output operands on stack.
        pushOutputValues(outputValueList);
    }

    @Override
    public void visitLDC(LDC obj) {
        Object constantValue = obj.getValue(cpg);
        ValueNumber value;
        if (constantValue instanceof ConstantClreplaced) {
            ConstantClreplaced constantClreplaced = (ConstantClreplaced) constantValue;
            String clreplacedName = constantClreplaced.getBytes(cpg.getConstantPool());
            value = factory.getClreplacedObjectValue(clreplacedName);
        } else if (constantValue instanceof ObjectType) {
            ObjectType objectType = (ObjectType) constantValue;
            String clreplacedName = objectType.getClreplacedName();
            value = factory.getClreplacedObjectValue(clreplacedName);
        } else {
            value = constantValueMap.get(constantValue);
            if (value == null) {
                value = factory.createFreshValue(ValueNumber.CONSTANT_VALUE);
                constantValueMap.put(constantValue, value);
                // Keep track of String constants
                if (constantValue instanceof String) {
                    stringConstantMap.put(value, (String) constantValue);
                }
            }
        }
        getFrame().pushValue(value);
    }

    @Override
    public void visitIINC(IINC obj) {
        if (obj.getIncrement() == 0) {
            // A no-op.
            return;
        }
        // IINC is a special case because its input and output are not on the
        // stack.
        // However, we still want to use the value number cache to ensure that
        // this operation is modeled consistently. (If we do nothing, we miss
        // the fact that the referenced local is modified.)
        int local = obj.getIndex();
        ValueNumber[] input = new ValueNumber[] { getFrame().getValue(local) };
        ValueNumberCache.Entry entry = new ValueNumberCache.Entry(handle, input);
        ValueNumber[] output = cache.lookupOutputValues(entry);
        if (output == null) {
            output = new ValueNumber[] { factory.createFreshValue() };
            cache.addOutputValues(entry, output);
        }
        getFrame().setValue(local, output[0]);
    }

    @Override
    public void visitCHECKCAST(CHECKCAST obj) {
    // Do nothing
    }

    /*
     * ----------------------------------------------------------------------
     * Implementation
     * ----------------------------------------------------------------------
     */
    /**
     * Pop the input values for the given instruction from the current frame.
     */
    private ValueNumber[] popInputValues(int numWordsConsumed) {
        ValueNumberFrame frame = getFrame();
        ValueNumber[] inputValueList = allocateValueNumberArray(numWordsConsumed);
        // Pop off the input operands.
        try {
            frame.getTopStackWords(inputValueList);
            while (numWordsConsumed-- > 0) {
                frame.popValue();
            }
        } catch (DataflowreplacedysisException e) {
            throw new InvalidBytecodeException("Error getting input operands", e);
        }
        return inputValueList;
    }

    /**
     * Push given output values onto the current frame.
     */
    private void pushOutputValues(ValueNumber[] outputValueList) {
        ValueNumberFrame frame = getFrame();
        for (ValueNumber aOutputValueList : outputValueList) {
            frame.pushValue(aOutputValueList);
        }
    }

    /**
     * Get output values for current instruction from the ValueNumberCache.
     */
    private ValueNumber[] getOutputValues(ValueNumber[] inputValueList, int numWordsProduced) {
        return getOutputValues(inputValueList, numWordsProduced, 0);
    }

    private ValueNumber[] getOutputValues(ValueNumber[] inputValueList, int numWordsProduced, int flags) {
        ValueNumberCache.Entry entry = new ValueNumberCache.Entry(handle, inputValueList);
        ValueNumber[] outputValueList = cache.lookupOutputValues(entry);
        if (outputValueList == null) {
            outputValueList = allocateValueNumberArray(numWordsProduced);
            for (int i = 0; i < numWordsProduced; ++i) {
                ValueNumber freshValue = factory.createFreshValue(flags);
                outputValueList[i] = freshValue;
            }
            /*
            if (false && RLE_DEBUG) {
                System.out.println("<<cache fill for " + handle.getPosition() + ": " + vlts(inputValueList) + " ==> "
                        + vlts(outputValueList) + ">>");
            }
             */
            cache.addOutputValues(entry, outputValueList);
        }
        /* else if (false && RLE_DEBUG) {
            System.out.println("<<cache hit for " + handle.getPosition() + ": " + vlts(inputValueList) + " ==> "
                    + vlts(outputValueList) + ">>");
          } */
        return outputValueList;
    }

    /**
     * Creates a new empty array (if needed) with given size.
     *
     * @param size
     *            array size
     * @return if size is zero, returns {@link #EMPTY_INPUT_VALUE_LIST}
     */
    private static ValueNumber[] allocateValueNumberArray(int size) {
        if (size == 0) {
            return EMPTY_INPUT_VALUE_LIST;
        }
        return new ValueNumber[size];
    }

    private static String vlts(ValueNumber[] vl) {
        StringBuilder buf = new StringBuilder();
        for (ValueNumber aVl : vl) {
            if (buf.length() > 0) {
                buf.append(',');
            }
            buf.append(aVl.getNumber());
        }
        return buf.toString();
    }

    /**
     * Load an instance field.
     *
     * @param instanceField
     *            the field
     * @param obj
     *            the Instruction loading the field
     */
    private void loadInstanceField(XField instanceField, Instruction obj) {
        if (RLE_DEBUG) {
            System.out.println("[loadInstanceField for field " + instanceField + " in instruction " + handle);
        }
        ValueNumberFrame frame = getFrame();
        try {
            ValueNumber reference = frame.popValue();
            AvailableLoad availableLoad = new AvailableLoad(reference, instanceField);
            if (RLE_DEBUG) {
                System.out.println("[getfield of " + availableLoad + "]");
            }
            ValueNumber[] loadedValue = frame.getAvailableLoad(availableLoad);
            if (loadedValue == null) {
                // Get (or create) the cached result for this instruction
                ValueNumber[] inputValueList = new ValueNumber[] { reference };
                loadedValue = getOutputValues(inputValueList, getNumWordsProduced(obj));
                // Make the load available
                frame.addAvailableLoad(availableLoad, loadedValue);
                if (RLE_DEBUG) {
                    System.out.println("[Making load available " + availableLoad + " <- " + vlts(loadedValue) + "]");
                }
            } else {
                // Found an available load!
                if (RLE_DEBUG) {
                    System.out.println("[Found available load " + availableLoad + " <- " + vlts(loadedValue) + "]");
                }
            }
            pushOutputValues(loadedValue);
            if (VERIFY_INTEGRITY) {
                checkConsumedAndProducedValues(obj, new ValueNumber[] { reference }, loadedValue);
            }
        } catch (DataflowreplacedysisException e) {
            throw new InvalidBytecodeException("Error loading from instance field", e);
        }
    }

    /**
     * Load a static field.
     *
     * @param staticField
     *            the field
     * @param obj
     *            the Instruction loading the field
     */
    private void loadStaticField(XField staticField, Instruction obj) {
        if (RLE_DEBUG) {
            System.out.println("[loadStaticField for field " + staticField + " in instruction " + handle);
        }
        ValueNumberFrame frame = getFrame();
        AvailableLoad availableLoad = new AvailableLoad(staticField);
        ValueNumber[] loadedValue = frame.getAvailableLoad(availableLoad);
        if (loadedValue == null) {
            // Make the load available
            int numWordsProduced = getNumWordsProduced(obj);
            loadedValue = getOutputValues(EMPTY_INPUT_VALUE_LIST, numWordsProduced);
            frame.addAvailableLoad(availableLoad, loadedValue);
            if (RLE_DEBUG) {
                System.out.println("[making load of " + staticField + " available]");
            }
        } else {
            if (RLE_DEBUG) {
                System.out.println("[found available load of " + staticField + "]");
            }
        }
        if (VERIFY_INTEGRITY) {
            checkConsumedAndProducedValues(obj, EMPTY_INPUT_VALUE_LIST, loadedValue);
        }
        pushOutputValues(loadedValue);
    }

    /**
     * Store an instance field.
     *
     * @param instanceField
     *            the field
     * @param obj
     *            the instruction which stores the field
     * @param pushStoredValue
     *            push the stored value onto the stack (because we are modeling
     *            an inner-clreplaced field access method)
     */
    private void storeInstanceField(XField instanceField, Instruction obj, boolean pushStoredValue) {
        if (RLE_DEBUG) {
            System.out.println("[storeInstanceField for field " + instanceField + " in instruction " + handle);
        }
        ValueNumberFrame frame = getFrame();
        int numWordsConsumed = getNumWordsConsumed(obj);
        /*
         * System.out.println("Instruction is " + handle);
         * System.out.println("numWordsConsumed="+numWordsConsumed);
         */
        ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
        ValueNumber reference = inputValueList[0];
        ValueNumber[] storedValue = allocateValueNumberArray(inputValueList.length - 1);
        System.arraycopy(inputValueList, 1, storedValue, 0, inputValueList.length - 1);
        if (pushStoredValue) {
            pushOutputValues(storedValue);
        }
        // Kill all previous loads of the same field,
        // in case there is aliasing we don't know about
        frame.killLoadsOfField(instanceField);
        // Forward subsreplacedution
        frame.addAvailableLoad(new AvailableLoad(reference, instanceField), storedValue);
        if (RLE_DEBUG) {
            System.out.println("[making store of " + instanceField + " available]");
        }
        if (VERIFY_INTEGRITY) {
            /*
             * System.out.println("pushStoredValue="+pushStoredValue);
             */
            checkConsumedAndProducedValues(obj, inputValueList, pushStoredValue ? storedValue : EMPTY_INPUT_VALUE_LIST);
        }
    }

    /**
     * Store a static field.
     *
     * @param staticField
     *            the static field
     * @param obj
     *            the instruction which stores the field
     * @param pushStoredValue
     *            push the stored value onto the stack (because we are modeling
     *            an inner-clreplaced field access method)
     */
    private void storeStaticField(XField staticField, Instruction obj, boolean pushStoredValue) {
        if (RLE_DEBUG) {
            System.out.println("[storeStaticField for field " + staticField + " in instruction " + handle);
        }
        ValueNumberFrame frame = getFrame();
        AvailableLoad availableLoad = new AvailableLoad(staticField);
        int numWordsConsumed = getNumWordsConsumed(obj);
        ValueNumber[] inputValueList = popInputValues(numWordsConsumed);
        if (pushStoredValue) {
            pushOutputValues(inputValueList);
        }
        // Kill loads of this field
        frame.killLoadsOfField(staticField);
        // Make load available
        frame.addAvailableLoad(availableLoad, inputValueList);
        if (RLE_DEBUG) {
            System.out.println("[making store of " + staticField + " available]");
        }
        if (VERIFY_INTEGRITY) {
            checkConsumedAndProducedValues(obj, inputValueList, pushStoredValue ? inputValueList : EMPTY_INPUT_VALUE_LIST);
        }
    }
}

19 Source : ValueNumberAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * <p>A dataflow replacedysis to track the production and flow of values in the Java
 * stack frame. See the {@link ValueNumber ValueNumber} clreplaced for an explanation
 * of what the value numbers mean, and when they can be compared.</p>
 *
 * <p>
 * This clreplaced is still experimental.</p>
 *
 * @author David Hovemeyer
 * @see ValueNumber
 * @see edu.umd.cs.findbugs.ba.Dominatorsreplacedysis
 */
public clreplaced ValueNumberreplacedysis extends FrameDataflowreplacedysis<ValueNumber, ValueNumberFrame> {

    private final static boolean TRACE = SystemProperties.getBoolean("vna.trace");

    public static final boolean DEBUG = TRACE || SystemProperties.getBoolean("vna.debug");

    private final MethodGen methodGen;

    private final ValueNumberFactory factory;

    private final ValueNumberFrameModelingVisitor visitor;

    private final ValueNumber[] entryLocalValueList;

    private final IdenreplacedyHashMap<BasicBlock, ValueNumber> exceptionHandlerValueNumberMap;

    private ValueNumber thisValue;

    private final HashMap<Location, ValueNumberFrame> factAtLocationMap;

    private final HashMap<Location, ValueNumberFrame> factAfterLocationMap;

    private MergeTree mergeTree;

    public ValueNumberreplacedysis(MethodGen methodGen, DepthFirstSearch dfs, LoadedFieldSet loadedFieldSet, RepositoryLookupFailureCallback lookupFailureCallback) {
        super(dfs);
        this.methodGen = methodGen;
        this.factory = new ValueNumberFactory();
        ValueNumberCache cache = new ValueNumberCache();
        this.visitor = new ValueNumberFrameModelingVisitor(methodGen, factory, cache, loadedFieldSet, lookupFailureCallback);
        int numLocals = methodGen.getMaxLocals();
        this.entryLocalValueList = new ValueNumber[numLocals];
        for (int i = 0; i < numLocals; ++i) {
            this.entryLocalValueList[i] = factory.createFreshValue();
        }
        this.exceptionHandlerValueNumberMap = new IdenreplacedyHashMap<>();
        // For non-static methods, keep track of which value represents the
        // "this" reference
        if (!methodGen.isStatic()) {
            this.thisValue = entryLocalValueList[0];
        }
        this.factAtLocationMap = new HashMap<>();
        this.factAfterLocationMap = new HashMap<>();
        if (DEBUG) {
            System.out.println("VNA replacedysis " + methodGen.getClreplacedName() + "." + methodGen.getName() + " : " + methodGen.getSignature());
        }
    }

    public ValueNumber getClreplacedObjectValue(String clreplacedName) {
        return visitor.factory.getClreplacedObjectValue(clreplacedName);
    }

    public void setMergeTree(MergeTree mergeTree) {
        this.mergeTree = mergeTree;
    }

    public MergeTree getMergeTree() {
        return mergeTree;
    }

    public ValueNumberFactory getFactory() {
        return factory;
    }

    public int getNumValuesAllocated() {
        return factory.getNumValuesAllocated();
    }

    public boolean isThisValue(ValueNumber value) {
        return thisValue != null && thisValue.getNumber() == value.getNumber();
    }

    public ValueNumber getThisValue() {
        return thisValue;
    }

    /**
     * Get the value number replacedigned to the given local variable upon entry to
     * the method.
     *
     * @param local
     *            local variable number
     * @return ValueNumber replacedigned to the local variable
     */
    public ValueNumber getEntryValue(int local) {
        return entryLocalValueList[local];
    }

    /**
     * Get the value number replacedigned to the given parameter upon entry to the
     * method.
     *
     * @param param
     *            a parameter (0 == first parameter)
     * @return the ValueNumber replacedigned to that parameter
     */
    public ValueNumber getEntryValueForParameter(int param) {
        SignatureParser sigParser = new SignatureParser(methodGen.getSignature());
        int p = 0;
        int slotOffset = methodGen.isStatic() ? 0 : 1;
        for (String paramSig : sigParser.parameterSignatures()) {
            if (p == param) {
                return getEntryValue(slotOffset);
            }
            p++;
            slotOffset += SignatureParser.getNumSlotsForType(paramSig);
        }
        throw new IllegalStateException();
    }

    @Override
    public ValueNumberFrame createFact() {
        return new ValueNumberFrame(methodGen.getMaxLocals());
    }

    @Override
    public void initEntryFact(ValueNumberFrame result) {
        // Change the frame from TOP to something valid.
        result.setValid();
        // At entry to the method, each local has (as far as we know) a unique
        // value.
        int numSlots = result.getNumSlots();
        for (int i = 0; i < numSlots; ++i) {
            result.setValue(i, entryLocalValueList[i]);
        }
    }

    @Override
    public void transfer(BasicBlock basicBlock, InstructionHandle end, ValueNumberFrame start, ValueNumberFrame result) throws DataflowreplacedysisException {
        if (basicBlock.isExceptionThrower() && isFactValid(start)) {
            /* If exceptionThrower is invoke instruction then it's possible that
             * it was partially executed before an exception occurred
             * So we have to kill available loads when control is transferred to the catch block
             */
            InstructionHandle handle = basicBlock.getExceptionThrower();
            Instruction inst = handle.getInstruction();
            if (inst instanceof InvokeInstruction) {
                copy(start, result);
                visitor.setFrameAndLocation(result, new Location(handle, basicBlock));
                visitor.setHandle(handle);
                visitor.visitInvokeOnException(inst);
                return;
            }
        }
        super.transfer(basicBlock, end, start, result);
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, ValueNumberFrame fact) throws DataflowreplacedysisException {
        Location location = new Location(handle, basicBlock);
        ValueNumberFrame atLocation = getFactAtLocation(location);
        copy(fact, atLocation);
        visitor.setFrameAndLocation(fact, location);
        visitor.setHandle(handle);
        visitor.replacedyzeInstruction(handle.getInstruction());
        ValueNumberFrame afterLocation = getFactAfterLocation(location);
        copy(fact, afterLocation);
    }

    @Override
    public void meetInto(ValueNumberFrame fact, Edge edge, ValueNumberFrame result) throws DataflowreplacedysisException {
        if (edge.getTarget().isExceptionHandler() && fact.isValid()) {
            // Special case: when merging predecessor facts for entry to
            // an exception handler, we clear the stack and push a
            // single entry for the exception object. That way, the locals
            // can still be merged.
            // Get the value number for the exception
            BasicBlock handlerBlock = edge.getTarget();
            ValueNumber exceptionValueNumber = getExceptionValueNumber(handlerBlock);
            // Set up the stack frame
            ValueNumberFrame tmpFact = createFact();
            tmpFact.copyFrom(fact);
            tmpFact.clearStack();
            tmpFact.pushValue(exceptionValueNumber);
            fact = tmpFact;
        }
        mergeInto(fact, result);
    }

    @Override
    protected void mergeInto(ValueNumberFrame frame, ValueNumberFrame result) throws DataflowreplacedysisException {
        result.mergeAvailableLoadSets(frame, factory, mergeTree);
        super.mergeInto(frame, result);
    }

    @Override
    protected void mergeValues(ValueNumberFrame otherFrame, ValueNumberFrame resultFrame, int slot) throws DataflowreplacedysisException {
        ValueNumber value = mergeValues(resultFrame, slot, resultFrame.getValue(slot), otherFrame.getValue(slot));
        resultFrame.setValue(slot, value);
    }

    private ValueNumber mergeValues(ValueNumberFrame frame, int slot, ValueNumber mine, ValueNumber other) {
        // Merging slot values:
        // - Merging identical values results in no change
        // - If the values are different, and the value in the result
        // frame is not the result of a previous result, a fresh value
        // is allocated.
        // - If the value in the result frame is the result of a
        // previous merge, IT STAYS THE SAME.
        // 
        // The "one merge" rule means that merged values are essentially like
        // phi nodes. They combine some number of other values.
        // I believe (but haven't proved) that this technique is a dumb way
        // of computing SSA.
        if (mine != frame.getValue(slot)) {
            throw new IllegalStateException();
        }
        if (mine.equals(other)) {
            return mine;
        }
        ValueNumber mergedValue = frame.getMergedValue(slot);
        if (mergedValue == null) {
            mergedValue = factory.createFreshValue(ValueNumber.mergeFlags(mine.getFlags(), other.getFlags()) | ValueNumber.PHI_NODE);
            frame.setMergedValue(slot, mergedValue);
        }
        if (mergeTree != null) {
            mergeTree.mapInputToOutput(mine, mergedValue);
            mergeTree.mapInputToOutput(other, mergedValue);
        }
        return mergedValue;
    }

    @Override
    public ValueNumberFrame getFactAtLocation(Location location) {
        ValueNumberFrame fact = factAtLocationMap.get(location);
        if (fact == null) {
            fact = createFact();
            makeFactTop(fact);
            factAtLocationMap.put(location, fact);
        }
        return fact;
    }

    @Override
    public ValueNumberFrame getFactAfterLocation(Location location) {
        if (TRACE) {
            System.out.println("getting fact after " + location);
        }
        ValueNumberFrame fact = factAfterLocationMap.get(location);
        if (fact == null) {
            if (TRACE) {
                System.out.println("Initialized fact after " + location + " @ " + Integer.toHexString(System.idenreplacedyHashCode(location)) + " in " + Integer.toHexString(System.idenreplacedyHashCode(this)) + " : " + factAfterLocationMap.containsKey(location));
            }
            fact = createFact();
            makeFactTop(fact);
            factAfterLocationMap.put(location, fact);
        }
        return fact;
    }

    /**
     * Get an Iterator over all dataflow facts that we've recorded for the
     * Locations in the CFG. Note that this does not include result facts (since
     * there are no Locations corresponding to the end of basic blocks).
     */
    public Iterator<ValueNumberFrame> facreplacederator() {
        return factAtLocationMap.values().iterator();
    }

    // These fields are used by the compactValueNumbers() method.
    /*
    private static clreplaced ValueCompacter {
        public final BitSet valuesUsed;
    
        public int numValuesUsed;
    
        public final int[] discovered;
    
        public ValueCompacter(int origNumValuesAllocated) {
            valuesUsed = new BitSet();
            numValuesUsed = 0;
    
            // The "discovered" array tells us the mapping of old value numbers
            // to new (which are based on order of discovery). Negative values
            // specify value numbers which are not actually used (and thus can
            // be purged.)
            discovered = new int[origNumValuesAllocated];
            for (int i = 0; i < discovered.length; ++i) {
                discovered[i] = -1;
            }
        }
    
        public boolean isUsed(int number) {
            return valuesUsed.get(number);
        }
    
        public void setUsed(int number) {
            valuesUsed.set(number, true);
        }
    
        public int allocateValue() {
            return numValuesUsed++;
        }
    }
     */
    /**
     * <p>Compact the value numbers replacedigned. This should be done only after the
     * dataflow algorithm has executed. This works by modifying the actual
     * ValueNumber objects replacedigned. After this method is called, the
     * getNumValuesAllocated() method of this object will return a value less
     * than or equal to the value it would have returned before the call to this
     * method.
     * </p>
     * <p>
     * <em>This method should be called at most once</em>.
     * </p>
     * @param dataflow
     *            the Dataflow object which executed this replacedysis (and has all
     *            of the block result values)
     */
    @Deprecated
    public void compactValueNumbers(Dataflow<ValueNumberFrame, ValueNumberreplacedysis> dataflow) {
        throw new UnsupportedOperationException();
    }

    /**
     * Mark value numbers in a value number frame for compaction.
     *
     *    private static void markFrameValues(ValueNumberFrame frame, ValueCompacter compacter) {
     *        // We don't need to do anything for top and bottom frames.
     *        if (!frame.isValid()) {
     *            return;
     *        }
     *
     *        for (int j = 0; j < frame.getNumSlots(); ++j) {
     *            ValueNumber value = frame.getValue(j);
     *            int number = value.getNumber();
     *
     *            if (!compacter.isUsed(number)) {
     *                compacter.discovered[number] = compacter.allocateValue();
     *                compacter.setUsed(number);
     *            }
     *        }
     *    }
     */
    // /**
    // * Test driver.
    // */
    // public static void main(String[] argv) throws Exception {
    // 
    // if (argv.length != 1) {
    // System.out.println("Usage: edu.umd.cs.findbugs.ba.ValueNumberreplacedysis <filename>");
    // System.exit(1);
    // }
    // 
    // DataflowTestDriver<ValueNumberFrame, ValueNumberreplacedysis> driver =
    // new DataflowTestDriver<ValueNumberFrame, ValueNumberreplacedysis>() {
    // @Override
    // public Dataflow<ValueNumberFrame, ValueNumberreplacedysis>
    // createDataflow(ClreplacedContext clreplacedContext, Method method)
    // throws CFGBuilderException, DataflowreplacedysisException {
    // return clreplacedContext.getValueNumberDataflow(method);
    // }
    // };
    // 
    // driver.execute(argv[0]);
    // }
    private ValueNumber getExceptionValueNumber(BasicBlock handlerBlock) {
        ValueNumber valueNumber = exceptionHandlerValueNumberMap.get(handlerBlock);
        if (valueNumber == null) {
            valueNumber = factory.createFreshValue();
            exceptionHandlerValueNumberMap.put(handlerBlock, valueNumber);
        }
        return valueNumber;
    }

    @CheckForNull
    @DottedClreplacedName
    public String getClreplacedName(ValueNumber v) {
        return factory.getClreplacedName(v);
    }
}

19 Source : SignatureConverter.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Convenience method for generating a method signature in human readable
 * form.
 *
 * @param methodGen
 *            the method to produce a method signature for
 */
public static String convertMethodSignature(MethodGen methodGen) {
    return convertMethodSignature(methodGen.getClreplacedName(), methodGen.getName(), methodGen.getSignature());
}

19 Source : ResourceValueAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

@javax.annotation.ParametersAreNonnullByDefault
public clreplaced ResourceValuereplacedysis<Resource> extends FrameDataflowreplacedysis<ResourceValue, ResourceValueFrame> implements EdgeTypes {

    private static final boolean DEBUG = SystemProperties.getBoolean("dataflow.debug");

    private final MethodGen methodGen;

    private final CFG cfg;

    private final ResourceTracker<Resource> resourceTracker;

    private final Resource resource;

    private final ResourceValueFrameModelingVisitor visitor;

    private final boolean ignoreImplicitExceptions;

    public ResourceValuereplacedysis(MethodGen methodGen, CFG cfg, DepthFirstSearch dfs, ResourceTracker<Resource> resourceTracker, Resource resource) {
        super(dfs);
        this.methodGen = methodGen;
        this.cfg = cfg;
        this.resourceTracker = resourceTracker;
        this.resource = resource;
        this.visitor = resourceTracker.createVisitor(resource, methodGen.getConstantPool());
        this.ignoreImplicitExceptions = resourceTracker.ignoreImplicitExceptions(resource);
    }

    @Override
    public ResourceValueFrame createFact() {
        ResourceValueFrame fact = new ResourceValueFrame(methodGen.getMaxLocals());
        fact.setTop();
        return fact;
    }

    @Override
    public void initEntryFact(ResourceValueFrame result) {
        result.setValid();
        result.clearStack();
        final int numSlots = result.getNumSlots();
        for (int i = 0; i < numSlots; ++i) {
            boolean slotContainsInstance = resourceTracker.isParamInstance(resource, i);
            result.setValue(i, slotContainsInstance ? ResourceValue.instance() : ResourceValue.notInstance());
        }
    }

    @Override
    public void meetInto(ResourceValueFrame fact, Edge edge, ResourceValueFrame result) throws DataflowreplacedysisException {
        BasicBlock source = edge.getSource();
        BasicBlock dest = edge.getTarget();
        ResourceValueFrame tmpFact = null;
        if (edge.isExceptionEdge()) {
            // If this edge throws only implicit exceptions
            // (as determined by Typereplacedysis and
            // PruneInfeasibleExceptionEdges),
            // and the resource tracker says to ignore implicit exceptions
            // for this resource, ignore it.
            if (replacedysisContext.currentreplacedysisContext().getBoolProperty(replacedysisFeatures.ACCURATE_EXCEPTIONS) && ignoreImplicitExceptions && !edge.isFlagSet(EXPLICIT_EXCEPTIONS_FLAG)) {
                return;
            }
            // The ResourceTracker may veto the exception edge
            if (resourceTracker.ignoreExceptionEdge(edge, resource, methodGen.getConstantPool())) {
                return;
            }
            if (fact.getStatus() == ResourceValueFrame.OPEN) {
                // If status is OPEN, downgrade to OPEN_ON_EXCEPTION_PATH
                tmpFact = modifyFrame(fact, null);
                tmpFact.setStatus(ResourceValueFrame.OPEN_ON_EXCEPTION_PATH);
            }
            if (fact.isValid()) {
                // Special case: if the instruction that closes the resource
                // throws an exception, we consider the resource to be
                // successfully
                // closed anyway.
                InstructionHandle exceptionThrower = source.getExceptionThrower();
                BasicBlock fallThroughSuccessor = cfg.getSuccessorWithEdgeType(source, FALL_THROUGH_EDGE);
                if (DEBUG && fallThroughSuccessor == null) {
                    System.out.println("Null fall through successor!");
                }
                if (fallThroughSuccessor != null && resourceTracker.isResourceClose(fallThroughSuccessor, exceptionThrower, methodGen.getConstantPool(), resource, fact)) {
                    tmpFact = modifyFrame(fact, tmpFact);
                    tmpFact.setStatus(ResourceValueFrame.CLOSED);
                    if (DEBUG) {
                        System.out.print("(failed attempt to close)");
                    }
                }
            }
            if (dest.isExceptionHandler()) {
                // Clear stack, push value for exception
                if (fact.isValid()) {
                    tmpFact = modifyFrame(fact, tmpFact);
                    tmpFact.clearStack();
                    tmpFact.pushValue(ResourceValue.notInstance());
                }
            }
        }
        // Make the resource nonexistent if it is compared against null
        int edgeType = edge.getType();
        if (edgeType == IFCMP_EDGE || edgeType == FALL_THROUGH_EDGE) {
            InstructionHandle lastInSourceHandle = source.getLastInstruction();
            if (lastInSourceHandle != null) {
                Instruction lastInSource = lastInSourceHandle.getInstruction();
                boolean isNullCheck = false;
                boolean isNonNullCheck = false;
                // This check catches null == X, null != X
                if (lastInSource instanceof IF_ACMPEQ || lastInSource instanceof IF_ACMPNE) {
                    Location l = new Location(lastInSourceHandle, source);
                    InstructionHandle ih = l.getHandle();
                    // Get instruction that pushed topmost
                    InstructionHandle ihPrev = ih.getPrev();
                    // Get next-topmost that pushed next-topmost
                    InstructionHandle ihPrevPrev = ihPrev == null ? null : ihPrev.getPrev();
                    int prevPush = 0;
                    if (ihPrev != null) {
                        prevPush = ihPrev.getInstruction().produceStack(methodGen.getConstantPool());
                    }
                    int prevPrevPush = 0;
                    if (ihPrevPrev != null) {
                        prevPrevPush = ihPrevPrev.getInstruction().produceStack(methodGen.getConstantPool());
                    }
                    // If instructions exist and both push one word onto the
                    // stack and the next-topmost pushes null...
                    if (ihPrev != null && ihPrevPrev != null && prevPush == 1 && prevPrevPush == 1 && ihPrevPrev.getInstruction().getOpcode() == Const.ACONST_NULL) {
                        // Topmost item on stack is being compared with null
                        // (the null itself is next-topmost on the stack)
                        isNullCheck = lastInSource instanceof IF_ACMPEQ;
                        isNonNullCheck = lastInSource instanceof IF_ACMPNE;
                    }
                } else // This check catches X == null, X != null
                if (lastInSource instanceof IFNULL || lastInSource instanceof IFNONNULL) {
                    isNullCheck = lastInSource instanceof IFNULL;
                    isNonNullCheck = lastInSource instanceof IFNONNULL;
                }
                if (isNullCheck || isNonNullCheck) {
                    // Get the frame at the if statement
                    ResourceValueFrame startFrame = getStartFact(source);
                    if (startFrame.isValid()) {
                        // The source block has a valid start fact.
                        // That means it is safe to inspect the frame at the If
                        // instruction.
                        ResourceValueFrame frameAtIf = getFactAtLocation(new Location(lastInSourceHandle, source));
                        ResourceValue topValue = frameAtIf.getValue(frameAtIf.getNumSlots() - 1);
                        if (topValue.isInstance()) {
                            if ((isNullCheck && edgeType == IFCMP_EDGE) || (isNonNullCheck && edgeType == FALL_THROUGH_EDGE)) {
                                // System.out.println("**** making resource nonexistent on edge "+edge.getId());
                                tmpFact = modifyFrame(fact, tmpFact);
                                tmpFact.setStatus(ResourceValueFrame.NONEXISTENT);
                            }
                        }
                    }
                }
            }
        }
        if (tmpFact != null) {
            fact = tmpFact;
        }
        mergeInto(fact, result);
    }

    @Override
    protected void mergeInto(ResourceValueFrame frame, ResourceValueFrame result) throws DataflowreplacedysisException {
        // Merge slots
        super.mergeInto(frame, result);
        // Merge status
        result.setStatus(Math.min(result.getStatus(), frame.getStatus()));
    }

    @Override
    protected void mergeValues(ResourceValueFrame otherFrame, ResourceValueFrame resultFrame, int slot) throws DataflowreplacedysisException {
        ResourceValue value = ResourceValue.merge(resultFrame.getValue(slot), otherFrame.getValue(slot));
        resultFrame.setValue(slot, value);
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, ResourceValueFrame fact) throws DataflowreplacedysisException {
        visitor.setFrameAndLocation(fact, new Location(handle, basicBlock));
        visitor.transferInstruction(handle, basicBlock);
    }
}

19 Source : PruneUnconditionalExceptionThrowerEdges.java
with GNU Lesser General Public License v2.1
from spotbugs

public clreplaced PruneUnconditionalExceptionThrowerEdges implements EdgeTypes {

    private static final boolean DEBUG = SystemProperties.getBoolean("cfg.prune.throwers.debug");

    private static final boolean DEBUG_DIFFERENCES = SystemProperties.getBoolean("cfg.prune.throwers.differences.debug");

    private static final String UNCONDITIONAL_THROWER_METHOD_NAMES = SystemProperties.getProperty("findbugs.unconditionalThrower", " ").replace(',', '|');

    private final MethodGen methodGen;

    private final CFG cfg;

    private final ConstantPoolGen cpg;

    private final TypeDataflow typeDataflow;

    private final replacedysisContext replacedysisContext;

    private boolean cfgModified;

    private static final Pattern unconditionalThrowerPattern;

    private static final BitSet RETURN_OPCODE_SET = new BitSet();

    static {
        RETURN_OPCODE_SET.set(Const.ARETURN);
        RETURN_OPCODE_SET.set(Const.IRETURN);
        RETURN_OPCODE_SET.set(Const.LRETURN);
        RETURN_OPCODE_SET.set(Const.DRETURN);
        RETURN_OPCODE_SET.set(Const.FRETURN);
        RETURN_OPCODE_SET.set(Const.RETURN);
        Pattern p;
        try {
            p = Pattern.compile(UNCONDITIONAL_THROWER_METHOD_NAMES);
            if (DEBUG) {
                System.out.println("Pattern is '" + p + "'");
                System.out.println(p.matcher("showInvalidPage").matches());
            }
        } catch (RuntimeException e) {
            replacedysisContext.logError("Error compiling unconditional thrower pattern " + UNCONDITIONAL_THROWER_METHOD_NAMES, e);
            p = Pattern.compile(" ");
        }
        unconditionalThrowerPattern = p;
    }

    public PruneUnconditionalExceptionThrowerEdges(/* ClreplacedContext clreplacedContext, */
    JavaClreplaced javaClreplaced, Method method, MethodGen methodGen, CFG cfg, ConstantPoolGen cpg, TypeDataflow typeDataflow, replacedysisContext replacedysisContext) {
        // this.clreplacedContext = clreplacedContext;
        this.methodGen = methodGen;
        this.cfg = cfg;
        this.cpg = cpg;
        this.typeDataflow = typeDataflow;
        this.replacedysisContext = replacedysisContext;
    }

    public void execute() throws DataflowreplacedysisException {
        replacedysisContext currentreplacedysisContext = replacedysisContext.currentreplacedysisContext();
        if (currentreplacedysisContext.getBoolProperty(replacedysisFeatures.CONSERVE_SPACE)) {
            throw new IllegalStateException("This should not happen");
        }
        boolean foundInexact = false;
        Set<Edge> deletedEdgeSet = new HashSet<>();
        // TypeDataflow typeDataflow = clreplacedContext.getTypeDataflow(method);
        if (DEBUG) {
            System.out.println("PruneUnconditionalExceptionThrowerEdges: examining " + SignatureConverter.convertMethodSignature(methodGen));
        }
        for (Iterator<BasicBlock> i = cfg.blockIterator(); i.hasNext(); ) {
            BasicBlock basicBlock = i.next();
            if (!basicBlock.isExceptionThrower()) {
                continue;
            }
            InstructionHandle instructionHandle = basicBlock.getExceptionThrower();
            Instruction exceptionThrower = instructionHandle.getInstruction();
            if (!(exceptionThrower instanceof InvokeInstruction)) {
                continue;
            }
            if (exceptionThrower instanceof INVOKEDYNAMIC) {
                continue;
            }
            InvokeInstruction inv = (InvokeInstruction) exceptionThrower;
            boolean foundThrower = false;
            boolean foundNonThrower = false;
            boolean isExact = true;
            XMethod primaryXMethod = XFactory.createXMethod(inv, cpg);
            final String methodName = primaryXMethod.getName();
            final boolean matches = unconditionalThrowerPattern.matcher(methodName).matches();
            if (DEBUG) {
                System.out.println("Checking '" + methodName + "' is " + matches);
            }
            if (matches) {
                if (DEBUG) {
                    System.out.println("\tmatched for " + instructionHandle + " : " + primaryXMethod);
                }
                foundThrower = true;
            } else if (inv instanceof INVOKEINTERFACE) {
                continue;
            } else if (inv instanceof INVOKESTATIC) {
                foundThrower = isUnconditionalThrower(primaryXMethod);
            } else {
                String clreplacedName = inv.getClreplacedName(cpg);
                if (DEBUG) {
                    System.out.println("\tlooking up method for " + instructionHandle + " : " + primaryXMethod);
                }
                Location loc = new Location(instructionHandle, basicBlock);
                TypeFrame typeFrame = typeDataflow.getFactAtLocation(loc);
                // if (primaryXMethod.isAbstract()) continue;
                Set<XMethod> targetSet = null;
                try {
                    if (clreplacedName.startsWith("[")) {
                        continue;
                    }
                    String methodSig = inv.getSignature(cpg);
                    if (!methodSig.endsWith("V") && !methodSig.endsWith("Exception;") && !methodSig.endsWith("Error;") && !methodSig.endsWith(")Ljava/lang/Object;")) {
                        continue;
                    }
                    targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, cpg);
                    for (XMethod xMethod : targetSet) {
                        if (DEBUG) {
                            System.out.println("\tFound " + xMethod);
                        }
                        // Ignore abstract and native methods
                        boolean isUnconditionalThrower = isUnconditionalThrower(xMethod);
                        if (isUnconditionalThrower) {
                            if (!(xMethod.isFinal() || xMethod.isStatic() || xMethod.isPrivate())) {
                                try {
                                    isExact = false;
                                    XClreplaced xClreplaced = Global.getreplacedysisCache().getClreplacedreplacedysis(XClreplaced.clreplaced, xMethod.getClreplacedDescriptor());
                                    if (xClreplaced.isAbstract()) {
                                        continue;
                                    }
                                } catch (CheckedreplacedysisException e) {
                                    replacedysisContext.logError("Unable to resolve clreplaced for " + xMethod, e);
                                }
                            }
                            foundThrower = true;
                            if (DEBUG) {
                                System.out.println("Found thrower");
                            }
                        } else {
                            foundNonThrower = true;
                            if (DEBUG) {
                                System.out.println("Found non thrower");
                            }
                        }
                    }
                } catch (ClreplacedNotFoundException e) {
                    replacedysisContext.getLookupFailureCallback().reportMissingClreplaced(e);
                }
            }
            boolean newResult = foundThrower && !foundNonThrower;
            if (newResult) {
                if (!isExact) {
                    foundInexact = true;
                }
                // Method always throws an unhandled exception
                // Remove the normal control flow edge from the CFG.
                Edge fallThrough = cfg.getOutgoingEdgeWithType(basicBlock, FALL_THROUGH_EDGE);
                if (fallThrough != null) {
                    if (DEBUG) {
                        System.out.println("\tREMOVING normal return for: " + primaryXMethod);
                    }
                    deletedEdgeSet.add(fallThrough);
                }
            }
        }
        if (!deletedEdgeSet.isEmpty()) {
            cfgModified = true;
            if (foundInexact) {
                cfg.setFlag(CFG.FOUND_INEXACT_UNCONDITIONAL_THROWERS);
            }
            // Remove all edges marked for deletion
            for (Edge edge : deletedEdgeSet) {
                cfg.removeEdge(edge);
            }
        }
    }

    private boolean isUnconditionalThrower(XMethod xMethod) {
        return xMethod.isUnconditionalThrower() && !xMethod.isUnsupported() && !xMethod.isSynthetic();
    }

    /**
     * @param xMethod
     * @param javaClreplaced
     * @param method
     * @return true if method unconditionally throws
     * @deprecated Use {@link #doesMethodUnconditionallyThrowException(XMethod)}
     *             instead
     */
    @Deprecated
    static public Boolean doesMethodUnconditionallyThrowException(XMethod xMethod, JavaClreplaced javaClreplaced, Method method) {
        return doesMethodUnconditionallyThrowException(xMethod);
    }

    /**
     * @param xMethod
     * @return true if method unconditionally throws
     */
    static public boolean doesMethodUnconditionallyThrowException(XMethod xMethod) {
        return xMethod.isUnconditionalThrower();
    }

    /**
     * Return whether or not the CFG was modified.
     *
     * @return true if CFG was modified, false otherwise
     */
    public boolean wasCFGModified() {
        return cfgModified;
    }
}

19 Source : LockAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * replacedysis to determine where particular values are locked in a method. The
 * dataflow values are maps of value numbers to the number of times those values
 * are locked.
 *
 * @author David Hovemeyer
 * @see ValueNumberreplacedysis
 */
public clreplaced Lockreplacedysis extends ForwardDataflowreplacedysis<LockSet> {

    private static final boolean DEBUG = SystemProperties.getBoolean("la.debug");

    private final MethodGen methodGen;

    private final ValueNumberDataflow vnaDataflow;

    private final ValueNumberreplacedysis vna;

    private final boolean isSynchronized;

    private final boolean isStatic;

    public Lockreplacedysis(MethodGen methodGen, ValueNumberDataflow vnaDataflow, DepthFirstSearch dfs) {
        super(dfs);
        this.methodGen = methodGen;
        this.vnaDataflow = vnaDataflow;
        this.vna = vnaDataflow.getreplacedysis();
        this.isSynchronized = methodGen.isSynchronized();
        this.isStatic = methodGen.isStatic();
        if (DEBUG) {
            System.out.println("replacedyzing Locks in " + methodGen.getClreplacedName() + "." + methodGen.getName());
        }
    }

    @Override
    public LockSet createFact() {
        return new LockSet();
    }

    @Override
    public void copy(LockSet source, LockSet dest) {
        dest.copyFrom(source);
    }

    @Override
    public void initEntryFact(LockSet result) {
        result.clear();
        result.setDefaultLockCount(0);
        if (isSynchronized && !isStatic) {
            ValueNumber thisValue = vna.getThisValue();
            result.setLockCount(thisValue.getNumber(), 1);
        } else if (isSynchronized && isStatic) {
            ValueNumber thisValue = vna.getClreplacedObjectValue(methodGen.getClreplacedName());
            result.setLockCount(thisValue.getNumber(), 1);
        }
    }

    @Override
    public void makeFactTop(LockSet fact) {
        fact.clear();
        fact.setDefaultLockCount(LockSet.TOP);
    }

    @Override
    public boolean isTop(LockSet fact) {
        return fact.isTop();
    }

    @Override
    public boolean same(LockSet fact1, LockSet fact2) {
        return fact1.sameAs(fact2);
    }

    @Override
    public void meetInto(LockSet fact, Edge edge, LockSet result) throws DataflowreplacedysisException {
        result.meetWith(fact);
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, LockSet fact) throws DataflowreplacedysisException {
        Instruction ins = handle.getInstruction();
        short opcode = ins.getOpcode();
        if (opcode == Const.MONITORENTER || opcode == Const.MONITOREXIT) {
            ValueNumberFrame frame = vnaDataflow.getFactAtLocation(new Location(handle, basicBlock));
            modifyLock(frame, fact, opcode == Const.MONITORENTER ? 1 : -1);
        } else if (opcode == Const.INVOKEVIRTUAL || opcode == Const.INVOKEINTERFACE) {
            InvokeInstruction inv = (InvokeInstruction) ins;
            String name = inv.getMethodName(methodGen.getConstantPool());
            String sig = inv.getSignature(methodGen.getConstantPool());
            ValueNumberFrame frame = vnaDataflow.getFactAtLocation(new Location(handle, basicBlock));
            if ("()V".equals(sig) && ("lock".equals(name) || "lockInterruptibly".equals(name))) {
                modifyLock(frame, fact, 1);
            } else if ("()V".equals(sig) && ("unlock".equals(name))) {
                modifyLock(frame, fact, -1);
            }
        } else if ((ins instanceof ReturnInstruction) && isSynchronized && !isStatic) {
            lockOp(fact, vna.getThisValue().getNumber(), -1);
        }
    }

    private void modifyLock(ValueNumberFrame frame, LockSet fact, int delta) throws DataflowreplacedysisException {
        if (frame.isValid()) {
            int lockNumber = frame.getTopValue().getNumber();
            lockOp(fact, lockNumber, delta);
        }
    }

    private void lockOp(LockSet fact, int lockNumber, int delta) {
        int value = fact.getLockCount(lockNumber);
        if (value < 0) {
            return;
        }
        value += delta;
        if (value < 0) {
            value = LockSet.BOTTOM;
        }
        if (DEBUG) {
            System.out.println("Setting " + lockNumber + " to " + value + " in " + methodGen.getClreplacedName() + "." + methodGen.getName());
        }
        fact.setLockCount(lockNumber, value);
    }

    @Override
    public boolean isFactValid(LockSet fact) {
        return true;
    }
    // public static void main(String[] argv) throws Exception {
    // if (argv.length != 1) {
    // System.err.println("Usage: " + Lockreplacedysis.clreplaced.getName() +
    // " <clreplacedfile>");
    // System.exit(1);
    // }
    // 
    // DataflowTestDriver<LockSet, Lockreplacedysis> driver = new
    // DataflowTestDriver<LockSet, Lockreplacedysis>() {
    // @Override
    // public Dataflow<LockSet, Lockreplacedysis> createDataflow(ClreplacedContext
    // clreplacedContext, Method method)
    // throws CFGBuilderException, DataflowreplacedysisException {
    // return clreplacedContext.getLockDataflow(method);
    // }
    // };
    // 
    // driver.execute(argv[0]);
    // }
}

19 Source : LineNumberMap.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Summarize line numbers (and other source information) for a method.
 */
public clreplaced LineNumberMap {

    /**
     * Set this property to true to get debug print statements.
     */
    private static final boolean DEBUG = SystemProperties.getBoolean("lnm.debug");

    /**
     * When this is true, the workaround for the bug in BCEL 5.0's
     * LineNumberTable clreplaced is disabled.
     */
    private static final boolean LINE_NUMBER_BUG = SystemProperties.getBoolean("lineNumberBug");

    private final MethodGen methodGen;

    private final IdenreplacedyHashMap<InstructionHandle, LineNumber> lineNumberMap;

    private boolean hasLineNumbers;

    /**
     * Constructor.
     *
     * @param methodGen
     *            the method to summarize line numbers for
     */
    public LineNumberMap(MethodGen methodGen) {
        this.methodGen = methodGen;
        lineNumberMap = new IdenreplacedyHashMap<>();
        hasLineNumbers = false;
    }

    /**
     * Build the line number information. Should be called before any other
     * methods.
     */
    public void build() {
        int numGood = 0, numBytecodes = 0;
        if (DEBUG) {
            System.out.println("Method: " + methodGen.getName() + " - " + methodGen.getSignature() + "in clreplaced " + methodGen.getClreplacedName());
        }
        // replacedociate line number information with each InstructionHandle
        LineNumberTable table = methodGen.getLineNumberTable(methodGen.getConstantPool());
        if (table != null && table.getTableLength() > 0) {
            checkTable(table);
            InstructionHandle handle = methodGen.getInstructionList().getStart();
            while (handle != null) {
                int bytecodeOffset = handle.getPosition();
                if (bytecodeOffset < 0) {
                    throw new IllegalStateException("Bad bytecode offset: " + bytecodeOffset);
                }
                if (DEBUG) {
                    System.out.println("Looking for source line for bytecode offset " + bytecodeOffset);
                }
                int sourceLine;
                try {
                    sourceLine = table.getSourceLine(bytecodeOffset);
                } catch (ArrayIndexOutOfBoundsException e) {
                    if (LINE_NUMBER_BUG) {
                        throw e;
                    } else {
                        sourceLine = -1;
                    }
                }
                if (sourceLine >= 0) {
                    ++numGood;
                }
                lineNumberMap.put(handle, new LineNumber(bytecodeOffset, sourceLine));
                handle = handle.getNext();
                ++numBytecodes;
            }
            hasLineNumbers = true;
            if (DEBUG) {
                System.out.println("\t" + numGood + "/" + numBytecodes + " had valid line numbers");
            }
        }
    }

    private void checkTable(LineNumberTable table) {
        if (DEBUG) {
            System.out.println("line number table has length " + table.getTableLength());
        }
        LineNumber[] entries = table.getLineNumberTable();
        int lastBytecode = -1;
        for (int i = 0; i < entries.length; ++i) {
            LineNumber ln = entries[i];
            if (DEBUG) {
                System.out.println("Entry " + i + ": pc=" + ln.getStartPC() + ", line=" + ln.getLineNumber());
            }
            int pc = ln.getStartPC();
            if (pc <= lastBytecode) {
                throw new IllegalStateException("LineNumberTable is not sorted");
            }
        }
    }

    /**
     * Does this method have line number information?
     */
    public boolean hasLineNumbers() {
        return hasLineNumbers;
    }

    /**
     * Find the line number information for instruction whose handle is given.
     *
     * @param handle
     *            the InstructionHandle
     * @return the LineNumber object containing bytecode offset and source line
     *         number
     */
    public LineNumber lookupLineNumber(InstructionHandle handle) {
        return lineNumberMap.get(handle);
    }
}

19 Source : ExceptionHandlerMap.java
with GNU Lesser General Public License v2.1
from spotbugs

private void build(MethodGen methodGen) {
    CodeExceptionGen[] handlerList = methodGen.getExceptionHandlers();
    // Map handler start instructions to the actual exception handlers
    for (CodeExceptionGen exceptionHandler : handlerList) {
        addExceptionHandler(exceptionHandler);
    }
    // For each instruction, determine which handlers it can reach
    InstructionHandle handle = methodGen.getInstructionList().getStart();
    while (handle != null) {
        int offset = handle.getPosition();
        handlerLoop: for (CodeExceptionGen exceptionHandler : handlerList) {
            int startOfRange = exceptionHandler.getStartPC().getPosition();
            int endOfRange = exceptionHandler.getEndPC().getPosition();
            if (offset >= startOfRange && offset <= endOfRange) {
                // This handler is reachable from the instruction
                addHandler(handle, exceptionHandler);
                // If this handler handles all exception types
                // i.e., an ANY handler, or catch(Throwable...),
                // then no further (lower-priority)
                // handlers are reachable from the instruction.
                if (Hierarchy.isUniversalExceptionHandler(exceptionHandler.getCatchType())) {
                    break handlerLoop;
                }
            }
        }
        handle = handle.getNext();
    }
}

19 Source : Dataflow.java
with GNU Lesser General Public License v2.1
from spotbugs

private String getFullyQualifiedMethodName() {
    String methodName;
    MethodGen methodGen = cfg.getMethodGen();
    if (methodGen == null) {
        methodName = cfg.getMethodName();
    } else {
        methodName = SignatureConverter.convertMethodSignature(methodGen);
    }
    return methodName;
}

19 Source : ConstantAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Dataflow replacedysis to find constant values.
 *
 * @see edu.umd.cs.findbugs.ba.constant.Constant
 * @author David Hovemeyer
 */
public clreplaced Constantreplacedysis extends FrameDataflowreplacedysis<Constant, ConstantFrame> {

    private final MethodGen methodGen;

    private final ConstantFrameModelingVisitor visitor;

    public Constantreplacedysis(MethodGen methodGen, DepthFirstSearch dfs) {
        super(dfs);
        this.methodGen = methodGen;
        this.visitor = new ConstantFrameModelingVisitor(methodGen.getConstantPool());
    }

    @Override
    public ConstantFrame createFact() {
        return new ConstantFrame(methodGen.getMaxLocals());
    }

    @Override
    public void initEntryFact(ConstantFrame frame) {
        frame.setValid();
        frame.clearStack();
        int numSlots = frame.getNumSlots();
        for (int i = 0; i < numSlots; ++i) {
            frame.setValue(i, Constant.NOT_CONSTANT);
        }
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, ConstantFrame frame) throws DataflowreplacedysisException {
        visitor.setFrameAndLocation(frame, new Location(handle, basicBlock));
        visitor.replacedyzeInstruction(handle.getInstruction());
    }

    @Override
    public void meetInto(ConstantFrame fact, Edge edge, ConstantFrame result) throws DataflowreplacedysisException {
        if (fact.isValid()) {
            ConstantFrame tmpFact = null;
            if (edge.isExceptionEdge()) {
                tmpFact = modifyFrame(fact, null);
                tmpFact.clearStack();
                tmpFact.pushValue(Constant.NOT_CONSTANT);
            }
            if (tmpFact != null) {
                fact = tmpFact;
            }
        }
        mergeInto(fact, result);
    }

    @Override
    protected void mergeValues(ConstantFrame otherFrame, ConstantFrame resultFrame, int slot) throws DataflowreplacedysisException {
        Constant value = Constant.merge(resultFrame.getValue(slot), otherFrame.getValue(slot));
        resultFrame.setValue(slot, value);
    }
    // /*
    // * Test driver.
    // */
    // public static void main(String[] argv) throws Exception {
    // if (argv.length != 1) {
    // System.err.println("Usage: " + Constantreplacedysis.clreplaced.getName() +
    // " <clreplaced file>");
    // System.exit(1);
    // }
    // 
    // DataflowTestDriver<ConstantFrame, Constantreplacedysis> driver =
    // new DataflowTestDriver<ConstantFrame, Constantreplacedysis>() {
    // @Override
    // public Dataflow<ConstantFrame, Constantreplacedysis> createDataflow(
    // ClreplacedContext clreplacedContext,
    // Method method) throws CFGBuilderException, DataflowreplacedysisException {
    // return clreplacedContext.getConstantDataflow(method);
    // }
    // };
    // 
    // driver.execute(argv[0]);
    // }
}

19 Source : CFGBuilderFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Create a CFGBuilder to build a CFG for given method.
 *
 * @param methodGen
 *            the method
 * @return a CFGBuilder for the method
 */
public static CFGBuilder create(@Nonnull MethodDescriptor descriptor, @Nonnull MethodGen methodGen) {
    return new BetterCFGBuilder2(descriptor, methodGen);
}

19 Source : CFG.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Simple control flow graph abstraction for BCEL.
 *
 * @see BasicBlock
 * @see Edge
 */
public clreplaced CFG extends AbstractGraph<Edge, BasicBlock> implements Debug {

    /*
     * ----------------------------------------------------------------------
     * CFG flags
     * ----------------------------------------------------------------------
     */
    /**
     * Flag set if infeasible exception edges have been pruned from the CFG.
     */
    public static final int PRUNED_INFEASIBLE_EXCEPTIONS = 1;

    /**
     * Flag set if normal return edges from calls to methods which
     * unconditionally throw an exception have been removed.
     */
    public static final int PRUNED_UNCONDITIONAL_THROWERS = 2;

    /**
     * Flag set if CFG has been "refined"; i.e., to the extent possible, all
     * infeasible edges have been removed.
     */
    public static final int REFINED = 4;

    /**
     * Flag set if CFG edges corresponding to failed replacedertions have been
     * removed.
     */
    public static final int PRUNED_FAILED_replacedERTION_EDGES = 8;

    /**
     * Flag set if CFG is busy (in the process of being refined.
     */
    public static final int BUSY = 16;

    public static final int FOUND_INEXACT_UNCONDITIONAL_THROWERS = 32;

    /*
     * ----------------------------------------------------------------------
     * Helper clreplacedes
     * ----------------------------------------------------------------------
     */
    /**
     * An Iterator over the Locations in the CFG. Because of JSR subroutines,
     * the same instruction may actually be part of multiple basic blocks (with
     * different facts true in each, due to calling context). Locations specify
     * both the instruction and the basic block.
     */
    private clreplaced LocationIterator implements Iterator<Location> {

        private final Iterator<BasicBlock> blockIter;

        private BasicBlock curBlock;

        private Iterator<InstructionHandle> instructionIter;

        private Location next;

        private LocationIterator() {
            this.blockIter = blockIterator();
            findNext();
        }

        @Override
        public boolean hasNext() {
            findNext();
            return next != null;
        }

        @Override
        public Location next() {
            findNext();
            if (next == null) {
                throw new NoSuchElementException();
            }
            Location result = next;
            next = null;
            return result;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        private void findNext() {
            while (next == null) {
                // Make sure we have an instruction iterator
                if (instructionIter == null) {
                    if (!blockIter.hasNext()) {
                        // At end
                        return;
                    }
                    curBlock = blockIter.next();
                    instructionIter = curBlock.instructionIterator();
                }
                if (instructionIter.hasNext()) {
                    next = new Location(instructionIter.next(), curBlock);
                } else {
                    // Go to next block
                    instructionIter = null;
                }
            }
        }
    }

    /*
     * ----------------------------------------------------------------------
     * Fields
     * ----------------------------------------------------------------------
     */
    private BasicBlock entry, exit;

    private int flags;

    // for informational purposes
    private String methodName;

    private MethodGen methodGen;

    private List<Edge> removedEdgeList;

    /*
     * ----------------------------------------------------------------------
     * Public methods
     * ----------------------------------------------------------------------
     */
    /**
     * Constructor. Creates empty control flow graph (with just entry and exit
     * nodes).
     */
    public CFG() {
    }

    /**
     * @param methodName
     *            The methodName to set.
     */
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public void setMethodGen(MethodGen methodGen) {
        this.methodGen = methodGen;
    }

    public MethodGen getMethodGen() {
        return methodGen;
    }

    /**
     * @return Returns the methodName.
     */
    public String getMethodName() {
        return methodName;
    }

    public String getMethodSig() {
        return methodGen.getSignature();
    }

    public void setFlags(int flags) {
        this.flags = flags;
    }

    public void setFlag(int flags) {
        this.flags |= flags;
    }

    public void clearFlag(int flags) {
        this.flags &= ~flags;
    }

    public int getFlags() {
        return flags;
    }

    public boolean isFlagSet(int flag) {
        return (flags & flag) != 0;
    }

    /**
     * Get the entry node.
     */
    public BasicBlock getEntry() {
        if (entry == null) {
            entry = allocate();
        }
        return entry;
    }

    /**
     * Get the exit node.
     */
    public BasicBlock getExit() {
        if (exit == null) {
            exit = allocate();
        }
        return exit;
    }

    /**
     * Add a unique edge to the graph. There must be no other edge already in
     * the CFG with the same source and destination blocks.
     *
     * @param source
     *            the source basic block
     * @param dest
     *            the destination basic block
     * @param type
     *            the type of edge; see constants in EdgeTypes interface
     * @return the newly created Edge
     * @throws IllegalStateException
     *             if there is already an edge in the CFG with the same source
     *             and destination block
     */
    public Edge createEdge(BasicBlock source, BasicBlock dest, @Edge.Type int type) {
        Edge edge = createEdge(source, dest);
        edge.setType(type);
        return edge;
    }

    /**
     * Look up an Edge by its id.
     *
     * @param id
     *            the id of the edge to look up
     * @return the Edge, or null if no matching Edge was found
     */
    public Edge lookupEdgeById(int id) {
        Iterator<Edge> i = edgeIterator();
        while (i.hasNext()) {
            Edge edge = i.next();
            if (edge.getId() == id) {
                return edge;
            }
        }
        return null;
    }

    /**
     * Look up a BasicBlock by its unique label.
     *
     * @param blockLabel
     *            the label of a BasicBlock
     * @return the BasicBlock with the given label, or null if there is no such
     *         BasicBlock
     */
    public BasicBlock lookupBlockByLabel(int blockLabel) {
        for (Iterator<BasicBlock> i = blockIterator(); i.hasNext(); ) {
            BasicBlock basicBlock = i.next();
            if (basicBlock.getLabel() == blockLabel) {
                return basicBlock;
            }
        }
        return null;
    }

    /**
     * Get an Iterator over the nodes (BasicBlocks) of the control flow graph.
     */
    public Iterator<BasicBlock> blockIterator() {
        return vertexIterator();
    }

    /*
     * * Get an Iteratable over the nodes (BasicBlocks) of the control flow
     * graph.
     */
    public Iterable<BasicBlock> blocks() {
        return vertices();
    }

    /**
     * Get an Iterator over the Locations in the control flow graph.
     */
    public Iterator<Location> locationIterator() {
        return new LocationIterator();
    }

    /**
     * Get an Iterator over the Locations in the control flow graph.
     */
    public Iterable<Location> locations() {
        return () -> locationIterator();
    }

    /**
     * Returns a collection of locations, ordered according to the compareTo
     * ordering over locations. If you want to list all the locations in a CFG
     * for debugging purposes, this is a good order to do so in.
     *
     * @return collection of locations
     */
    public Collection<Location> orderedLocations() {
        TreeSet<Location> tree = new TreeSet<>();
        for (Iterator<Location> locs = locationIterator(); locs.hasNext(); ) {
            Location loc = locs.next();
            tree.add(loc);
        }
        return tree;
    }

    /**
     * Get Collection of basic blocks whose IDs are specified by given BitSet.
     *
     * @param labelSet
     *            BitSet of block labels
     * @return a Collection containing the blocks whose IDs are given
     */
    public Collection<BasicBlock> getBlocks(BitSet labelSet) {
        LinkedList<BasicBlock> result = new LinkedList<>();
        for (Iterator<BasicBlock> i = blockIterator(); i.hasNext(); ) {
            BasicBlock block = i.next();
            if (labelSet.get(block.getLabel())) {
                result.add(block);
            }
        }
        return result;
    }

    /**
     * Get a Collection of basic blocks which contain the bytecode instruction
     * with given offset.
     *
     * @param offset
     *            the bytecode offset of an instruction
     * @return Collection of BasicBlock objects which contain the instruction
     *         with that offset
     */
    public Collection<BasicBlock> getBlocksContainingInstructionWithOffset(int offset) {
        LinkedList<BasicBlock> result = new LinkedList<>();
        for (Iterator<BasicBlock> i = blockIterator(); i.hasNext(); ) {
            BasicBlock block = i.next();
            if (block.containsInstructionWithOffset(offset)) {
                result.add(block);
            }
        }
        return result;
    }

    /**
     * Get a Collection of Locations which specify the instruction at given
     * bytecode offset.
     *
     * @param offset
     *            the bytecode offset
     * @return all Locations referring to the instruction at that offset
     */
    public Collection<Location> getLocationsContainingInstructionWithOffset(int offset) {
        LinkedList<Location> result = new LinkedList<>();
        for (Iterator<Location> i = locationIterator(); i.hasNext(); ) {
            Location location = i.next();
            if (location.getHandle().getPosition() == offset) {
                result.add(location);
            }
        }
        return result;
    }

    /**
     * Get the first predecessor reachable from given edge type.
     *
     * @param target
     *            the target block
     * @param edgeType
     *            the edge type leading from the predecessor
     * @return the predecessor, or null if there is no incoming edge with the
     *         specified edge type
     */
    public BasicBlock getPredecessorWithEdgeType(BasicBlock target, @Type int edgeType) {
        Edge edge = getIncomingEdgeWithType(target, edgeType);
        return edge != null ? edge.getSource() : null;
    }

    /**
     * Get the first successor reachable from given edge type.
     *
     * @param source
     *            the source block
     * @param edgeType
     *            the edge type leading to the successor
     * @return the successor, or null if there is no outgoing edge with the
     *         specified edge type
     */
    public BasicBlock getSuccessorWithEdgeType(BasicBlock source, @Type int edgeType) {
        Edge edge = getOutgoingEdgeWithType(source, edgeType);
        return edge != null ? edge.getTarget() : null;
    }

    /**
     * Get the Location where exception(s) thrown on given exception edge are
     * thrown.
     *
     * @param exceptionEdge
     *            the exception Edge
     * @return Location where exception(s) are thrown from
     */
    public Location getExceptionThrowerLocation(Edge exceptionEdge) {
        if (!exceptionEdge.isExceptionEdge()) {
            throw new IllegalArgumentException();
        }
        InstructionHandle handle = exceptionEdge.getSource().getExceptionThrower();
        if (handle == null) {
            throw new IllegalStateException();
        }
        BasicBlock basicBlock = (handle.getInstruction() instanceof ATHROW) ? exceptionEdge.getSource() : getSuccessorWithEdgeType(exceptionEdge.getSource(), EdgeTypes.FALL_THROUGH_EDGE);
        if (basicBlock == null && removedEdgeList != null) {
            // The fall-through edge might have been removed during
            // CFG pruning. Look for it in the removed edge list.
            for (Edge removedEdge : removedEdgeList) {
                if (removedEdge.getType() == EdgeTypes.FALL_THROUGH_EDGE && removedEdge.getSource() == exceptionEdge.getSource()) {
                    basicBlock = removedEdge.getTarget();
                    break;
                }
            }
        }
        if (basicBlock == null) {
            throw new IllegalStateException("No basic block for thrower " + handle + " in " + this.methodGen.getClreplacedName() + "." + this.methodName + " : " + this.methodGen.getSignature());
        }
        return new Location(handle, basicBlock);
    }

    /**
     * Get an Iterator over Edges removed from this CFG.
     *
     * @return Iterator over Edges removed from this CFG
     */
    public Iterator<Edge> removedEdgeIterator() {
        return removedEdgeList != null ? removedEdgeList.iterator() : new NullIterator<>();
    }

    /**
     * Get the first incoming edge in basic block with given type.
     *
     * @param basicBlock
     *            the basic block
     * @param edgeType
     *            the edge type
     * @return the Edge, or null if there is no edge with that edge type
     */
    public Edge getIncomingEdgeWithType(BasicBlock basicBlock, @Type int edgeType) {
        return getEdgeWithType(incomingEdgeIterator(basicBlock), edgeType);
    }

    /**
     * Get the first outgoing edge in basic block with given type.
     *
     * @param basicBlock
     *            the basic block
     * @param edgeType
     *            the edge type
     * @return the Edge, or null if there is no edge with that edge type
     */
    public Edge getOutgoingEdgeWithType(BasicBlock basicBlock, @Type int edgeType) {
        return getEdgeWithType(outgoingEdgeIterator(basicBlock), edgeType);
    }

    private Edge getEdgeWithType(Iterator<Edge> iter, @Type int edgeType) {
        while (iter.hasNext()) {
            Edge edge = iter.next();
            if (edge.getType() == edgeType) {
                return edge;
            }
        }
        return null;
    }

    /**
     * Allocate a new BasicBlock. The block won't be connected to any node in
     * the graph.
     */
    public BasicBlock allocate() {
        BasicBlock b = new BasicBlock();
        addVertex(b);
        return b;
    }

    /**
     * Get number of basic blocks. This is just here for compatibility with the
     * old CFG method names.
     */
    public int getNumBasicBlocks() {
        return getNumVertices();
    }

    /**
     * Get the number of edge labels allocated. This is just here for
     * compatibility with the old CFG method names.
     */
    public int getMaxEdgeId() {
        return getNumEdgeLabels();
    }

    public void checkIntegrity() {
        // Ensure that basic blocks have only consecutive instructions
        for (Iterator<BasicBlock> i = blockIterator(); i.hasNext(); ) {
            BasicBlock basicBlock = i.next();
            InstructionHandle prev = null;
            for (Iterator<InstructionHandle> j = basicBlock.instructionIterator(); j.hasNext(); ) {
                InstructionHandle handle = j.next();
                if (prev != null && prev.getNext() != handle) {
                    throw new IllegalStateException("Non-consecutive instructions in block " + basicBlock.getLabel() + ": prev=" + prev + ", handle=" + handle);
                }
                prev = handle;
            }
        }
    }

    @Override
    protected Edge allocateEdge(BasicBlock source, BasicBlock target) {
        return new Edge(source, target);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.graph.AbstractGraph#removeEdge(edu.umd.cs.findbugs
     * .graph.AbstractEdge)
     */
    @Override
    public void removeEdge(Edge edge) {
        super.removeEdge(edge);
        // Keep track of removed edges.
        if (removedEdgeList == null) {
            removedEdgeList = new LinkedList<>();
        }
        removedEdgeList.add(edge);
    }

    /**
     * Get number of non-exception control successors of given basic block.
     *
     * @param block
     *            a BasicBlock
     * @return number of non-exception control successors of the basic block
     */
    public int getNumNonExceptionSucessors(BasicBlock block) {
        int numNonExceptionSuccessors = block.getNumNonExceptionSuccessors();
        if (numNonExceptionSuccessors < 0) {
            numNonExceptionSuccessors = 0;
            for (Iterator<Edge> i = outgoingEdgeIterator(block); i.hasNext(); ) {
                Edge edge = i.next();
                if (!edge.isExceptionEdge()) {
                    numNonExceptionSuccessors++;
                }
            }
            block.setNumNonExceptionSuccessors(numNonExceptionSuccessors);
        }
        return numNonExceptionSuccessors;
    }

    /**
     * Get the Location representing the entry to the CFG. Note that this is a
     * "fake" Location, and shouldn't be relied on to yield source line
     * information.
     *
     * @return Location at entry to CFG
     */
    public Location getLocationAtEntry() {
        InstructionHandle handle = getEntry().getFirstInstruction();
        replacedert handle != null;
        return new Location(handle, getEntry());
    }

    public Location getPreviousLocation(Location loc) {
        InstructionHandle handle = loc.getHandle();
        BasicBlock basicBlock = loc.getBasicBlock();
        if (basicBlock.getFirstInstruction().equals(handle)) {
            BasicBlock prevBlock = basicBlock;
            while (true) {
                prevBlock = getPredecessorWithEdgeType(prevBlock, EdgeTypes.FALL_THROUGH_EDGE);
                if (prevBlock == null) {
                    return loc;
                }
                handle = prevBlock.getLastInstruction();
                if (handle != null) {
                    return new Location(handle, prevBlock);
                }
            }
        } else {
            handle = handle.getPrev();
            return new Location(handle, basicBlock);
        }
    }
}

19 Source : CFG.java
with GNU Lesser General Public License v2.1
from spotbugs

public void setMethodGen(MethodGen methodGen) {
    this.methodGen = methodGen;
}

19 Source : BetterCFGBuilder2.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * A CFGBuilder that really tries to construct accurate control flow graphs. The
 * CFGs it creates have accurate exception edges, and have accurately inlined
 * JSR subroutines.
 *
 * @author David Hovemeyer
 * @see CFG
 */
public clreplaced BetterCFGBuilder2 implements CFGBuilder, EdgeTypes, Debug {

    private static final boolean DEBUG = SystemProperties.getBoolean("cfgbuilder.debug");

    /*
     * ----------------------------------------------------------------------
     * Helper clreplacedes
     * ----------------------------------------------------------------------
     */
    /**
     * A work list item for creating the CFG for a subroutine.
     */
    private static clreplaced WorkLisreplacedem {

        private final InstructionHandle start;

        private final BasicBlock basicBlock;

        /**
         * Constructor.
         *
         * @param start
         *            first instruction in the basic block
         * @param basicBlock
         *            the basic block to build
         */
        public WorkLisreplacedem(InstructionHandle start, BasicBlock basicBlock) {
            this.start = start;
            this.basicBlock = basicBlock;
        }

        /**
         * Get the start instruction.
         */
        public InstructionHandle getStartInstruction() {
            return start;
        }

        /**
         * Get the basic block.
         */
        public BasicBlock getBasicBlock() {
            return basicBlock;
        }
    }

    /**
     * A placeholder for a control edge that escapes its subroutine to return
     * control back to an outer (calling) subroutine. It will turn into a real
     * edge during inlining.
     */
    private static clreplaced EscapeTarget {

        private final InstructionHandle target;

        @Edge.Type
        private final int edgeType;

        /**
         * Constructor.
         *
         * @param target
         *            the target instruction in a calling subroutine
         * @param edgeType
         *            the type of edge that should be created when the
         *            subroutine is inlined into its calling context
         */
        public EscapeTarget(InstructionHandle target, @Edge.Type int edgeType) {
            this.target = target;
            this.edgeType = edgeType;
        }

        /**
         * Get the target instruction.
         */
        public InstructionHandle getTarget() {
            return target;
        }

        /**
         * Get the edge type.
         */
        @Edge.Type
        public int getEdgeType() {
            return edgeType;
        }
    }

    /**
     * JSR subroutine. The top level subroutine is where execution starts. Each
     * subroutine has its own CFG. Eventually, all JSR subroutines will be
     * inlined into the top level subroutine, resulting in an accurate CFG for
     * the overall method.
     */
    private clreplaced Subroutine {

        private final InstructionHandle start;

        private final BitSet instructionSet;

        private final CFG cfgSub;

        private final IdenreplacedyHashMap<InstructionHandle, BasicBlock> blockMap;

        private final IdenreplacedyHashMap<BasicBlock, List<EscapeTarget>> escapeTargetListMap;

        private final BitSet returnBlockSet;

        private final BitSet exitBlockSet;

        private final BitSet unhandledExceptionBlockSet;

        private final LinkedList<WorkLisreplacedem> workList;

        /**
         * Constructor.
         *
         * @param start
         *            the start instruction for the subroutine
         */
        public Subroutine(InstructionHandle start) {
            this.start = start;
            this.instructionSet = new BitSet();
            this.cfgSub = new CFG();
            this.blockMap = new IdenreplacedyHashMap<>();
            this.escapeTargetListMap = new IdenreplacedyHashMap<>();
            this.returnBlockSet = new BitSet();
            this.exitBlockSet = new BitSet();
            this.unhandledExceptionBlockSet = new BitSet();
            this.workList = new LinkedList<>();
        }

        /**
         * Get the start instruction.
         */
        public InstructionHandle getStartInstruction() {
            return start;
        }

        /**
         * Allocate a new basic block in the subroutine.
         */
        public BasicBlock allocateBasicBlock() {
            return cfgSub.allocate();
        }

        /**
         * Add a work list item for a basic block to be constructed.
         */
        public void addItem(WorkLisreplacedem item) {
            workList.add(item);
        }

        /**
         * Are there more work list items?
         */
        public boolean hasMoreWork() {
            return !workList.isEmpty();
        }

        /**
         * Get the next work list item.
         */
        public WorkLisreplacedem nexreplacedem() {
            return workList.removeFirst();
        }

        /**
         * Get the entry block for the subroutine's CFG.
         */
        public BasicBlock getEntry() {
            return cfgSub.getEntry();
        }

        /**
         * Get the exit block for the subroutine's CFG.
         */
        public BasicBlock getExit() {
            return cfgSub.getExit();
        }

        /**
         * Get the start block for the subroutine's CFG. (I.e., the block
         * containing the start instruction.)
         */
        public BasicBlock getStartBlock() {
            return getBlock(start);
        }

        /**
         * Get the subroutine's CFG.
         */
        public CFG getCFG() {
            return cfgSub;
        }

        /**
         * Add an instruction to the subroutine. We keep track of which
         * instructions are part of which subroutines. No instruction may be
         * part of more than one subroutine.
         *
         * @param handle
         *            the instruction to be added to the subroutine
         */
        public void addInstruction(InstructionHandle handle) throws CFGBuilderException {
            int position = handle.getPosition();
            if (usedInstructionSet.get(position)) {
                throw new CFGBuilderException("Instruction " + handle + " visited in multiple subroutines");
            }
            instructionSet.set(position);
            usedInstructionSet.set(position);
        }

        /**
         * Is the given instruction part of this subroutine?
         */
        public boolean containsInstruction(InstructionHandle handle) {
            return instructionSet.get(handle.getPosition());
        }

        /**
         * Get the basic block in the subroutine for the given instruction. If
         * the block doesn't exist yet, it is created, and a work list item is
         * added which will populate it. Note that if start is an exception
         * thrower, the block returned will be its ETB.
         *
         * @param start
         *            the start instruction for the block
         * @return the basic block for the instruction
         */
        public BasicBlock getBlock(InstructionHandle start) {
            BasicBlock block = blockMap.get(start);
            if (block == null) {
                block = allocateBasicBlock();
                blockMap.put(start, block);
                // Block is an exception handler?
                CodeExceptionGen exceptionGen = exceptionHandlerMap.getHandlerForStartInstruction(start);
                if (exceptionGen != null) {
                    block.setExceptionGen(null, exceptionGen);
                }
                addItem(new WorkLisreplacedem(start, block));
            }
            return block;
        }

        /**
         * Indicate that the method returns at the end of the given block.
         *
         * @param block
         *            the returning block
         */
        public void setReturnBlock(BasicBlock block) {
            returnBlockSet.set(block.getLabel());
        }

        /**
         * Does the method return at the end of this block?
         */
        public boolean isReturnBlock(BasicBlock block) {
            return returnBlockSet.get(block.getLabel());
        }

        /**
         * Indicate that System.exit() is called at the end of the given block.
         *
         * @param block
         *            the exiting block
         */
        public void setExitBlock(BasicBlock block) {
            exitBlockSet.set(block.getLabel());
        }

        /**
         * Is System.exit() called at the end of this block?
         */
        public boolean isExitBlock(BasicBlock block) {
            return exitBlockSet.get(block.getLabel());
        }

        /**
         * Indicate that an unhandled exception may be thrown by the given
         * block.
         *
         * @param block
         *            the block throwing an unhandled exception
         */
        public void setUnhandledExceptionBlock(BasicBlock block) {
            unhandledExceptionBlockSet.set(block.getLabel());
        }

        /**
         * Does this block throw an unhandled exception?
         */
        public boolean isUnhandledExceptionBlock(BasicBlock block) {
            return unhandledExceptionBlockSet.get(block.getLabel());
        }

        /**
         * Add a control flow edge to the subroutine. If the control target has
         * not yet been added to the subroutine, a new work list item is added.
         * If the control target is in another subroutine, an EscapeTarget is
         * added.
         *
         * @param sourceBlock
         *            the source basic block
         * @param target
         *            the control target
         * @param edgeType
         *            the type of control edge
         */
        public void addEdgeAndExplore(BasicBlock sourceBlock, InstructionHandle target, @Edge.Type int edgeType) {
            if (usedInstructionSet.get(target.getPosition()) && !containsInstruction(target)) {
                // Control escapes this subroutine
                List<EscapeTarget> escapeTargetList = escapeTargetListMap.computeIfAbsent(sourceBlock, k -> new LinkedList<>());
                escapeTargetList.add(new EscapeTarget(target, edgeType));
            } else {
                // Edge within the current subroutine
                BasicBlock targetBlock = getBlock(target);
                addEdge(sourceBlock, targetBlock, edgeType);
            }
        }

        /**
         * Add an edge to the subroutine's CFG.
         *
         * @param sourceBlock
         *            the source basic block
         * @param destBlock
         *            the destination basic block
         * @param edgeType
         *            the type of edge
         */
        public void addEdge(BasicBlock sourceBlock, BasicBlock destBlock, @Edge.Type int edgeType) {
            if (VERIFY_INTEGRITY && destBlock.isExceptionHandler() && edgeType != HANDLED_EXCEPTION_EDGE) {
                throw new IllegalStateException("In method " + SignatureConverter.convertMethodSignature(methodGen) + ": exception handler " + destBlock.getFirstInstruction() + " reachable by non exception edge type " + edgeType);
            }
            cfgSub.createEdge(sourceBlock, destBlock, edgeType);
        }

        /**
         * Get an Iterator over the EscapeTargets of given basic block.
         *
         * @param sourceBlock
         *            the basic block
         * @return an Iterator over the EscapeTargets
         */
        public Iterator<EscapeTarget> escapeTargereplacederator(BasicBlock sourceBlock) {
            List<EscapeTarget> escapeTargetList = escapeTargetListMap.get(sourceBlock);
            if (escapeTargetList == null) {
                escapeTargetList = Collections.emptyList();
            }
            return escapeTargetList.iterator();
        }
    }

    /**
     * Inlining context. This essentially consists of a inlining site and a
     * subroutine to be inlined. A stack of calling contexts is maintained in
     * order to resolve EscapeTargets.
     */
    private static clreplaced Context {

        private final Context caller;

        private final Subroutine subroutine;

        private final CFG result;

        private final IdenreplacedyHashMap<BasicBlock, BasicBlock> blockMap;

        private final LinkedList<BasicBlock> workList;

        /**
         * Constructor.
         *
         * @param caller
         *            the calling context
         * @param subroutine
         *            the subroutine being inlined
         * @param result
         *            the result CFG
         */
        public Context(@Nullable Context caller, Subroutine subroutine, CFG result) {
            this.caller = caller;
            this.subroutine = subroutine;
            this.result = result;
            this.blockMap = new IdenreplacedyHashMap<>();
            this.workList = new LinkedList<>();
        }

        /**
         * Get the calling context.
         */
        public Context getCaller() {
            return caller;
        }

        /**
         * Get the subroutine being inlined.
         */
        public Subroutine getSubroutine() {
            return subroutine;
        }

        /**
         * Get the result CFG.
         */
        public CFG getResult() {
            return result;
        }

        /**
         * Add a basic block to the inlining work list.
         *
         *        public void addItem(BasicBlock item) {
         *            workList.add(item);
         *        }
         */
        /**
         * Are there more work list items?
         */
        public boolean hasMoreWork() {
            return !workList.isEmpty();
        }

        /**
         * Get the next work list item (basic block to be inlined).
         */
        public BasicBlock nexreplacedem() {
            return workList.removeFirst();
        }

        /**
         * Map a basic block in a subroutine to the corresponding block in the
         * resulting CFG.
         *
         * @param subBlock
         *            the subroutine block
         * @param resultBlock
         *            the result CFG block
         */
        public void mapBlock(BasicBlock subBlock, BasicBlock resultBlock) {
            blockMap.put(subBlock, resultBlock);
        }

        /**
         * Get the block in the result CFG corresponding to the given subroutine
         * block.
         *
         * @param subBlock
         *            the subroutine block
         * @return the result CFG block
         */
        public BasicBlock getBlock(BasicBlock subBlock) {
            BasicBlock resultBlock = blockMap.get(subBlock);
            if (resultBlock == null) {
                resultBlock = result.allocate();
                blockMap.put(subBlock, resultBlock);
                workList.add(subBlock);
            }
            return resultBlock;
        }

        /**
         * Check to ensure that this context is not the result of recursion.
         */
        public void checkForRecursion() throws CFGBuilderException {
            Context callerContext = caller;
            while (callerContext != null) {
                if (callerContext.subroutine == this.subroutine) {
                    throw new CFGBuilderException("JSR recursion detected!");
                }
                callerContext = callerContext.caller;
            }
        }
    }

    /*
     * ----------------------------------------------------------------------
     * Instance data
     * ----------------------------------------------------------------------
     */
    private final MethodGen methodGen;

    private final ConstantPoolGen cpg;

    private final ExceptionHandlerMap exceptionHandlerMap;

    private final BitSet usedInstructionSet;

    private final LinkedList<Subroutine> subroutineWorkList;

    private final IdenreplacedyHashMap<InstructionHandle, Subroutine> jsrSubroutineMap;

    private final Map<FieldDescriptor, Integer> addedFields = new HashMap<>();

    private Subroutine topLevelSubroutine;

    private CFG cfg;

    /*
     * ----------------------------------------------------------------------
     * Public methods
     * ----------------------------------------------------------------------
     */
    /**
     * Constructor.
     *
     * @param methodGen
     *            the method to build a CFG for
     */
    public BetterCFGBuilder2(@Nonnull MethodDescriptor descriptor, @Nonnull MethodGen methodGen) {
        this.methodGen = methodGen;
        this.cpg = methodGen.getConstantPool();
        IreplacedysisCache replacedysisCache = Global.getreplacedysisCache();
        StandardTypeMerger merger = null;
        ExceptionSetFactory exceptionSetFactory;
        try {
            exceptionSetFactory = replacedysisCache.getMethodreplacedysis(ExceptionSetFactory.clreplaced, descriptor);
            merger = new StandardTypeMerger(replacedysisContext.currentreplacedysisContext().getLookupFailureCallback(), exceptionSetFactory);
        } catch (CheckedreplacedysisException e) {
            replacedysisContext.logError("Unable to generate exceptionSetFactory for " + descriptor, e);
        }
        this.exceptionHandlerMap = new ExceptionHandlerMap(methodGen, merger);
        this.usedInstructionSet = new BitSet();
        this.jsrSubroutineMap = new IdenreplacedyHashMap<>();
        this.subroutineWorkList = new LinkedList<>();
    }

    public int getIndex(FieldDescriptor f) {
        Integer i = addedFields.get(f);
        if (i != null) {
            return i;
        }
        int index = cpg.addFieldref(f.getSlashedClreplacedName(), f.getName(), f.getSignature());
        addedFields.put(f, index);
        return index;
    }

    public void optimize(InstructionList instructionList) {
        InstructionHandle head = instructionList.getStart();
        while (head != null) {
            Instruction i = head.getInstruction();
            if (i instanceof INVOKESTATIC) {
                INVOKESTATIC is = (INVOKESTATIC) i;
                String name = is.getMethodName(cpg);
                String signature = is.getSignature(cpg);
                if (name.startsWith("access$")) {
                    XMethod invoked = XFactory.createXMethod(is, cpg);
                    FieldDescriptor field = invoked.getAccessMethodForField();
                    if (field != null) {
                        boolean isSetter = signature.endsWith("V");
                        Instruction replacement;
                        int index = getIndex(field);
                        if (field.isStatic()) {
                            if (isSetter) {
                                replacement = new PUTSTATIC(index);
                            } else {
                                replacement = new GETSTATIC(index);
                            }
                        } else {
                            if (isSetter) {
                                replacement = new PUTFIELD(index);
                            } else {
                                replacement = new GETFIELD(index);
                            }
                        }
                        head.swapInstruction(replacement);
                    /*
                            if (false)
                                System.out.println("Subsreplaceduting " + (isSetter ? "set" : "get") + " of " + field + " for call of "
                                    + invoked + " in " + methodGen.getClreplacedName() + "." + methodGen.getName()
                                    + methodGen.getSignature());
                         */
                    }
                }
            }
            if (i instanceof IfInstruction) {
                IfInstruction ii = (IfInstruction) i;
                InstructionHandle target = ii.getTarget();
                InstructionHandle next = head.getNext();
                if (target.equals(next)) {
                    int consumed = ii.consumeStack(methodGen.getConstantPool());
                    if (consumed != 1 && consumed != 2) {
                        throw new IllegalStateException();
                    }
                    head.swapInstruction(consumed == 1 ? new POP() : new POP2());
                }
            }
            if (i instanceof IFNULL || i instanceof IFNONNULL) {
                IfInstruction ii = (IfInstruction) i;
                InstructionHandle target = ii.getTarget();
                // ICONST
                InstructionHandle next1 = head.getNext();
                if (next1 == null) {
                    break;
                }
                if (next1.getInstruction() instanceof ICONST) {
                    // GOTO
                    InstructionHandle next2 = next1.getNext();
                    if (next2 == null) {
                        break;
                    }
                    // ICONST
                    InstructionHandle next3 = next2.getNext();
                    if (next3 == null) {
                        break;
                    }
                    InstructionHandle next4 = next3.getNext();
                    if (next4 == null) {
                        break;
                    }
                    if (target.equals(next3) && next2.getInstruction() instanceof GOTO && next3.getInstruction() instanceof ICONST && next1.getTargeters().length == 0 && next2.getTargeters().length == 0 && next3.getTargeters().length == 1 && next4.getTargeters().length == 1) {
                        int c1 = ((ICONST) next1.getInstruction()).getValue().intValue();
                        GOTO g = (GOTO) next2.getInstruction();
                        int c2 = ((ICONST) next3.getInstruction()).getValue().intValue();
                        if (g.getTarget().equals(next4) && (c1 == 1 && c2 == 0 || c1 == 0 && c2 == 1)) {
                            boolean nullIsTrue = i instanceof IFNULL && c2 == 1 || i instanceof IFNONNULL && c2 == 0;
                            if (nullIsTrue) {
                                // System.out.println("Found NULL2Z instruction");
                                head.swapInstruction(new NULL2Z());
                            } else {
                                // System.out.println("Found NONNULL2Z instruction");
                                head.swapInstruction(new NONNULL2Z());
                            }
                            next3.removeAllTargeters();
                            next4.removeAllTargeters();
                            next1.swapInstruction(new NOP());
                            next2.swapInstruction(new NOP());
                            next3.swapInstruction(new NOP());
                        }
                    }
                }
            }
            if (i instanceof ACONST_NULL) {
                InstructionHandle next = head.getNext();
                replacedert next != null;
                InstructionHandle next2 = next.getNext();
                if (next2 != null && next.getInstruction() instanceof ALOAD) {
                    Instruction check = next2.getInstruction();
                    if (check instanceof IF_ACMPNE || check instanceof IF_ACMPEQ) {
                        // need to update
                        head.swapInstruction(new NOP());
                        IfInstruction ifTest = (IfInstruction) check;
                        if (check instanceof IF_ACMPNE) {
                            next2.swapInstruction(new IFNONNULL(ifTest.getTarget()));
                        } else {
                            next2.swapInstruction(new IFNULL(ifTest.getTarget()));
                        }
                    }
                }
            }
            head = head.getNext();
        }
    }

    @Override
    public void build() throws CFGBuilderException {
        InstructionList instructionList = methodGen.getInstructionList();
        optimize(instructionList);
        topLevelSubroutine = new Subroutine(instructionList.getStart());
        subroutineWorkList.add(topLevelSubroutine);
        // Build top level subroutine and all JSR subroutines
        while (!subroutineWorkList.isEmpty()) {
            Subroutine subroutine = subroutineWorkList.removeFirst();
            if (DEBUG) {
                System.out.println("Starting subroutine " + subroutine.getStartInstruction());
            }
            build(subroutine);
        }
        // Inline everything into the top level subroutine
        cfg = inlineAll();
        // Add a NOP instruction to the entry block.
        // This allows replacedyses to construct a Location
        // representing the entry to the method.
        BasicBlock entryBlock = cfg.getEntry();
        InstructionList il = new InstructionList();
        entryBlock.addInstruction(il.append(new NOP()));
        cfg.checkIntegrity();
    }

    @Override
    public CFG getCFG() {
        return cfg;
    }

    /*
     * ----------------------------------------------------------------------
     * Implementation
     * ----------------------------------------------------------------------
     */
    /**
     * Build a subroutine. We iteratively add basic blocks to the subroutine
     * until there are no more blocks reachable from the calling context. As JSR
     * instructions are encountered, new Subroutines are added to the subroutine
     * work list.
     *
     * @param subroutine
     *            the subroutine
     */
    private void build(Subroutine subroutine) throws CFGBuilderException {
        // Prime the work list
        subroutine.addEdgeAndExplore(subroutine.getEntry(), subroutine.getStartInstruction(), START_EDGE);
        // Keep going until all basic blocks in the subroutine have been added
        while (subroutine.hasMoreWork()) {
            WorkLisreplacedem item = subroutine.nexreplacedem();
            InstructionHandle handle = item.getStartInstruction();
            BasicBlock basicBlock = item.getBasicBlock();
            // Add exception handler block (ETB) for exception-throwing
            // instructions
            if (isPEI(handle)) {
                if (DEBUG) {
                    System.out.println("ETB block " + basicBlock.getLabel() + " for " + handle);
                }
                handleExceptions(subroutine, handle, basicBlock);
                BasicBlock body = subroutine.allocateBasicBlock();
                subroutine.addEdge(basicBlock, body, FALL_THROUGH_EDGE);
                basicBlock = body;
            }
            if (DEBUG) {
                System.out.println("BODY block " + basicBlock.getLabel() + " for " + handle);
            }
            if (!basicBlock.isEmpty()) {
                throw new IllegalStateException("Block isn't empty!");
            }
            // Add instructions until we get to the end of the block
            boolean endOfBasicBlock = false;
            do {
                Instruction ins = handle.getInstruction();
                // Add the instruction to the block
                if (DEBUG) {
                    System.out.println("BB " + basicBlock.getLabel() + ": adding" + handle);
                }
                basicBlock.addInstruction(handle);
                subroutine.addInstruction(handle);
                short opcode = ins.getOpcode();
                // TODO: should check instruction to ensure that in a JSR
                // subroutine
                // no replacedignments are made to the local containing the return
                // address.
                // if (ins instanceof ASTORE) ...
                if (opcode == Const.JSR || opcode == Const.JSR_W) {
                    // Find JSR subroutine, add it to subroutine work list if
                    // we haven't built a CFG for it yet
                    JsrInstruction jsr = (JsrInstruction) ins;
                    InstructionHandle jsrTarget = jsr.getTarget();
                    Subroutine jsrSubroutine = jsrSubroutineMap.get(jsrTarget);
                    if (jsrSubroutine == null) {
                        jsrSubroutine = new Subroutine(jsrTarget);
                        jsrSubroutineMap.put(jsrTarget, jsrSubroutine);
                        subroutineWorkList.add(jsrSubroutine);
                    }
                    // This ends the basic block.
                    // Add a JSR_EDGE to the successor.
                    // It will be replaced later by the inlined JSR subroutine.
                    subroutine.addEdgeAndExplore(basicBlock, handle.getNext(), JSR_EDGE);
                    endOfBasicBlock = true;
                } else if (opcode == Const.RET) {
                    // End of JSR subroutine
                    subroutine.addEdge(basicBlock, subroutine.getExit(), RET_EDGE);
                    endOfBasicBlock = true;
                } else {
                    TargetEnumeratingVisitor visitor = new TargetEnumeratingVisitor(handle, cpg);
                    if (visitor.isEndOfBasicBlock()) {
                        endOfBasicBlock = true;
                        // Add control edges as appropriate
                        if (visitor.instructionIsThrow()) {
                            handleExceptions(subroutine, handle, basicBlock);
                        } else if (visitor.instructionIsExit()) {
                            subroutine.setExitBlock(basicBlock);
                        } else if (visitor.instructionIsReturn()) {
                            subroutine.setReturnBlock(basicBlock);
                        } else {
                            Iterator<Target> i = visitor.targereplacederator();
                            while (i.hasNext()) {
                                Target target = i.next();
                                subroutine.addEdgeAndExplore(basicBlock, target.getTargetInstruction(), target.getEdgeType());
                            }
                        }
                    }
                }
                if (!endOfBasicBlock) {
                    InstructionHandle next = handle.getNext();
                    if (next == null) {
                        throw new CFGBuilderException("Control falls off end of method: " + handle);
                    }
                    // Is the next instruction a control merge or a PEI?
                    if (isMerge(next) || isPEI(next)) {
                        subroutine.addEdgeAndExplore(basicBlock, next, FALL_THROUGH_EDGE);
                        endOfBasicBlock = true;
                    } else {
                        // Basic block continues
                        handle = next;
                    }
                }
            } while (!endOfBasicBlock);
        }
    }

    /**
     * Add exception edges for given instruction.
     *
     * @param subroutine
     *            the subroutine containing the instruction
     * @param pei
     *            the instruction which throws an exception
     * @param etb
     *            the exception thrower block (ETB) for the instruction
     */
    private void handleExceptions(Subroutine subroutine, InstructionHandle pei, BasicBlock etb) {
        etb.setExceptionThrower(pei);
        // Remember whether or not a universal exception handler
        // is reachable. If so, then we know that exceptions raised
        // at this instruction cannot propagate out of the method.
        boolean sawUniversalExceptionHandler = false;
        List<CodeExceptionGen> exceptionHandlerList = exceptionHandlerMap.getHandlerList(pei);
        if (exceptionHandlerList != null) {
            for (CodeExceptionGen exceptionHandler : exceptionHandlerList) {
                InstructionHandle handlerStart = exceptionHandler.getHandlerPC();
                subroutine.addEdgeAndExplore(etb, handlerStart, HANDLED_EXCEPTION_EDGE);
                if (Hierarchy.isUniversalExceptionHandler(exceptionHandler.getCatchType())) {
                    sawUniversalExceptionHandler = true;
                }
            }
        }
        // If required, mark this block as throwing an unhandled exception.
        // For now, we replacedume that if there is no reachable handler that handles
        // ANY exception type, then the exception can be thrown out of the
        // method.
        if (!sawUniversalExceptionHandler) {
            if (DEBUG) {
                System.out.println("Adding unhandled exception edge from " + pei);
            }
            subroutine.setUnhandledExceptionBlock(etb);
        }
    }

    /**
     * Return whether or not the given instruction can throw exceptions.
     *
     * @param handle
     *            the instruction
     * @return true if the instruction can throw an exception, false otherwise
     * @throws CFGBuilderException
     */
    private boolean isPEI(InstructionHandle handle) throws CFGBuilderException {
        Instruction ins = handle.getInstruction();
        if (!(ins instanceof ExceptionThrower)) {
            return false;
        }
        if (ins instanceof NEW) {
            return false;
        }
        // if (ins instanceof ATHROW) return false;
        if (ins instanceof GETSTATIC) {
            return false;
        }
        if (ins instanceof PUTSTATIC) {
            return false;
        }
        if (ins instanceof ReturnInstruction) {
            return false;
        }
        if (ins instanceof INSTANCEOF) {
            return false;
        }
        if (ins instanceof MONITOREXIT) {
            return false;
        }
        if (ins instanceof LDC) {
            return false;
        }
        if (ins instanceof GETFIELD && !methodGen.isStatic()) {
            // replacedume that GETFIELD on this object is not PEI
            return !isSafeFieldSource(handle.getPrev());
        }
        if (ins instanceof PUTFIELD && !methodGen.isStatic()) {
            // replacedume that PUTFIELD on this object is not PEI
            int depth = ins.consumeStack(cpg);
            for (InstructionHandle prev = handle.getPrev(); prev != null; prev = prev.getPrev()) {
                Instruction prevInst = prev.getInstruction();
                if (prevInst instanceof BranchInstruction) {
                    if (prevInst instanceof GotoInstruction) {
                        // Currently we support only jumps to the PUTFIELD itself
                        // This will cover simple cases like this.a = flag ? foo : bar
                        if (((BranchInstruction) prevInst).getTarget() == handle) {
                            depth = ins.consumeStack(cpg);
                        } else {
                            return true;
                        }
                    } else if (!(prevInst instanceof IfInstruction)) {
                        // As IF instructions may fall through then the stack depth remains unchanged
                        // Actually we should not go here for normal Java bytecode: switch or jsr should not appear in this context
                        return true;
                    }
                }
                depth = depth - prevInst.produceStack(cpg) + prevInst.consumeStack(cpg);
                if (depth < 1) {
                    throw new CFGBuilderException("Invalid stack at " + prev + " when checking " + handle);
                }
                if (depth == 1) {
                    InstructionHandle prevPrev = prev.getPrev();
                    if (prevPrev != null && prevPrev.getInstruction() instanceof BranchInstruction) {
                        continue;
                    }
                    return !isSafeFieldSource(prevPrev);
                }
            }
        }
        return true;
    }

    /**
     * @param handle instruction handle which loads the object for further GETFIELD/PUTFIELD operation
     * @return true if this object is known to be non-null
     */
    private boolean isSafeFieldSource(InstructionHandle handle) {
        while (handle != null && handle.getInstruction().getOpcode() == Const.DUP) {
            // Some compilers generate DUP for field increment code like
            // ALOAD_0 / DUP / GETFIELD x / ICONST_1 / IADD / PUTFIELD x
            handle = handle.getPrev();
        }
        if (handle == null) {
            return false;
        }
        Instruction inst = handle.getInstruction();
        if (inst.getOpcode() == Const.ALOAD_0) {
            return true;
        }
        return inst instanceof GETFIELD && ((GETFIELD) inst).getFieldName(cpg).startsWith("this$");
    }

    /**
     * Determine whether or not the given instruction is a control flow merge.
     *
     * @param handle
     *            the instruction
     * @return true if the instruction is a control merge, false otherwise
     */
    private static boolean isMerge(InstructionHandle handle) {
        if (handle.hasTargeters()) {
            // Check all targeters of this handle to see if any
            // of them are branches. If so, the instruction is a merge.
            InstructionTargeter[] targeterList = handle.getTargeters();
            for (InstructionTargeter targeter : targeterList) {
                if (targeter instanceof BranchInstruction) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Inline all JSR subroutines into the top-level subroutine. This produces a
     * complete CFG for the entire method, in which all JSR subroutines are
     * inlined.
     *
     * @return the CFG for the method
     */
    private CFG inlineAll() throws CFGBuilderException {
        CFG result = new CFG();
        Context rootContext = new Context(null, topLevelSubroutine, result);
        rootContext.mapBlock(topLevelSubroutine.getEntry(), result.getEntry());
        rootContext.mapBlock(topLevelSubroutine.getExit(), result.getExit());
        BasicBlock resultStartBlock = rootContext.getBlock(topLevelSubroutine.getStartBlock());
        result.createEdge(result.getEntry(), resultStartBlock, START_EDGE);
        inline(rootContext);
        return result;
    }

    /**
     * Inline a subroutine into a calling context.
     *
     * @param context
     *            the Context
     */
    public void inline(Context context) throws CFGBuilderException {
        CFG result = context.getResult();
        // Check to ensure we're not trying to inline something that is
        // recursive
        context.checkForRecursion();
        Subroutine subroutine = context.getSubroutine();
        CFG subCFG = subroutine.getCFG();
        while (context.hasMoreWork()) {
            BasicBlock subBlock = context.nexreplacedem();
            BasicBlock resultBlock = context.getBlock(subBlock);
            // Mark blocks which are in JSR subroutines
            resultBlock.setInJSRSubroutine(context.getCaller() != null);
            // Copy instructions into the result block
            BasicBlock.InstructionIterator insIter = subBlock.instructionIterator();
            while (insIter.hasNext()) {
                InstructionHandle handle = insIter.next();
                resultBlock.addInstruction(handle);
            }
            // Set exception thrower status
            if (subBlock.isExceptionThrower()) {
                resultBlock.setExceptionThrower(subBlock.getExceptionThrower());
            }
            // Set exception handler status
            if (subBlock.isExceptionHandler()) {
                resultBlock.setExceptionGen(null, subBlock.getExceptionGen());
            }
            // Add control edges (including inlining JSR subroutines)
            Iterator<Edge> edgeIter = subCFG.outgoingEdgeIterator(subBlock);
            while (edgeIter.hasNext()) {
                Edge edge = edgeIter.next();
                int edgeType = edge.getType();
                if (edgeType == JSR_EDGE) {
                    // Inline a JSR subroutine...
                    // Create a new Context
                    InstructionHandle jsrHandle = subBlock.getLastInstruction();
                    JsrInstruction jsr = (JsrInstruction) jsrHandle.getInstruction();
                    Subroutine jsrSub = jsrSubroutineMap.get(jsr.getTarget());
                    Context jsrContext = new Context(context, jsrSub, context.getResult());
                    // The start block in the JSR subroutine maps to the first
                    // inlined block in the result CFG.
                    BasicBlock resultJSRStartBlock = jsrContext.getBlock(jsrSub.getStartBlock());
                    result.createEdge(resultBlock, resultJSRStartBlock, GOTO_EDGE);
                    // The exit block in the JSR subroutine maps to the result
                    // block
                    // corresponding to the instruction following the JSR.
                    // (I.e., that is where control returns after the execution
                    // of
                    // the JSR subroutine.)
                    BasicBlock subJSRSuccessorBlock = subroutine.getBlock(jsrHandle.getNext());
                    BasicBlock resultJSRSuccessorBlock = context.getBlock(subJSRSuccessorBlock);
                    jsrContext.mapBlock(jsrSub.getExit(), resultJSRSuccessorBlock);
                    // Inline the JSR subroutine
                    inline(jsrContext);
                } else {
                    // Ordinary control edge
                    BasicBlock resultTarget = context.getBlock(edge.getTarget());
                    result.createEdge(resultBlock, resultTarget, edge.getType());
                }
            }
            // Add control edges for escape targets
            Iterator<EscapeTarget> escapeTargereplaceder = subroutine.escapeTargereplacederator(subBlock);
            while (escapeTargereplaceder.hasNext()) {
                EscapeTarget escapeTarget = escapeTargereplaceder.next();
                InstructionHandle targetInstruction = escapeTarget.getTarget();
                // Look for the calling context which has the target instruction
                Context caller = context.getCaller();
                while (caller != null) {
                    if (caller.getSubroutine().containsInstruction(targetInstruction)) {
                        break;
                    }
                    caller = caller.getCaller();
                }
                if (caller == null) {
                    throw new CFGBuilderException("Unknown caller for escape target " + targetInstruction + " referenced by " + context.getSubroutine().getStartInstruction());
                }
                // Find result block in caller
                BasicBlock subCallerTargetBlock = caller.getSubroutine().getBlock(targetInstruction);
                BasicBlock resultCallerTargetBlock = caller.getBlock(subCallerTargetBlock);
                // Add an edge to caller context
                result.createEdge(resultBlock, resultCallerTargetBlock, escapeTarget.getEdgeType());
            }
            // If the block returns from the method, add a return edge
            if (subroutine.isReturnBlock(subBlock)) {
                result.createEdge(resultBlock, result.getExit(), RETURN_EDGE);
            }
            // If the block calls System.exit(), add an exit edge
            if (subroutine.isExitBlock(subBlock)) {
                result.createEdge(resultBlock, result.getExit(), EXIT_EDGE);
            }
            // If the block throws an unhandled exception, add an unhandled
            // exception edge
            if (subroutine.isUnhandledExceptionBlock(subBlock)) {
                result.createEdge(resultBlock, result.getExit(), UNHANDLED_EXCEPTION_EDGE);
            }
        }
    /*
         * while (blocks are left) {
         *
         * get block from subroutine get corresponding block from result copy
         * instructions into result block
         *
         * if (block terminated by JSR) { get JSR subroutine create new context
         * create GOTO edge from current result block to start block of new
         * inlined context map subroutine exit block to result JSR successor
         * block inline (new context, result) } else { for each outgoing edge {
         * map each target to result blocks (add block to to work list if
         * needed) add edges to result }
         *
         * for each outgoing escape target { add edges into blocks in outer
         * contexts (adding those blocks to outer work list if needed) }
         *
         * if (block returns) { add return edge from result block to result CFG
         * exit block }
         *
         * if (block calls System.exit()) { add exit edge from result block to
         * result CFG exit block }
         *
         * if (block throws unhandled exception) { add unhandled exception edge
         * from result block to result CFG exit block } }
         *
         * }
         */
    }

    /**
     * Test driver.
     */
    public static void main(String[] argv) throws Exception {
        if (argv.length != 1) {
            System.err.println("Usage: " + BetterCFGBuilder2.clreplaced.getName() + " <clreplaced file>");
            System.exit(1);
        }
        String methodName = SystemProperties.getProperty("cfgbuilder.method");
        JavaClreplaced jclreplaced = new ClreplacedParser(argv[0]).parse();
        ClreplacedGen clreplacedGen = new ClreplacedGen(jclreplaced);
        Method[] methodList = jclreplaced.getMethods();
        for (Method method : methodList) {
            if (method.isAbstract() || method.isNative()) {
                continue;
            }
            if (methodName != null && !method.getName().equals(methodName)) {
                continue;
            }
            MethodDescriptor descriptor = DescriptorFactory.instance().getMethodDescriptor(jclreplaced, method);
            MethodGen methodGen = new MethodGen(method, jclreplaced.getClreplacedName(), clreplacedGen.getConstantPool());
            CFGBuilder cfgBuilder = new BetterCFGBuilder2(descriptor, methodGen);
            cfgBuilder.build();
            CFG cfg = cfgBuilder.getCFG();
            CFGPrinter cfgPrinter = new CFGPrinter(cfg);
            System.out.println("---------------------------------------------------------------------");
            System.out.println("Method: " + SignatureConverter.convertMethodSignature(methodGen));
            System.out.println("---------------------------------------------------------------------");
            cfgPrinter.print(System.out);
        }
    }
}

19 Source : TaintDataflowEngine.java
with GNU Lesser General Public License v3.0
from blackarbiter

private static String getSlashedMethodName(MethodGen methodGen) {
    String methodNameWithSignature = methodGen.getName() + methodGen.getSignature();
    String slashedClreplacedName = methodGen.getClreplacedName().replace('.', '/');
    return slashedClreplacedName + "." + methodNameWithSignature;
}

19 Source : TaintAnalysis.java
with GNU Lesser General Public License v3.0
from blackarbiter

/**
 * Implements taint dataflow operations, in particular meeting facts, transfer
 * function is delegated to {@link TaintFrameModelingVisitor}
 *
 * @author David Formanek (Y Soft Corporation, a.s.)
 */
public clreplaced Taintreplacedysis extends FrameDataflowreplacedysis<Taint, TaintFrame> {

    private final MethodGen methodGen;

    private final MethodInfo methodDescriptor;

    private final TaintFrameModelingVisitor visitor;

    private int parameterStackSize;

    private List<Integer> slotToParameter;

    private static final List<String> TAINTED_ANNOTATIONS = loadFileContent("taint-config/taint-param-annotations.txt");

    /**
     * Constructs replacedysis for the given method
     *
     * @param methodGen method to replacedyze
     * @param dfs DFS algorithm
     * @param descriptor descriptor of the method to replacedyze
     * @param taintConfig configured and derived taint summaries
     */
    public Taintreplacedysis(MethodGen methodGen, DepthFirstSearch dfs, MethodDescriptor descriptor, TaintConfig taintConfig) {
        super(dfs);
        this.methodGen = methodGen;
        this.methodDescriptor = (MethodInfo) descriptor;
        this.visitor = new TaintFrameModelingVisitor(methodGen.getConstantPool(), descriptor, taintConfig);
        computeParametersInfo(descriptor.getSignature(), descriptor.isStatic());
    }

    @Override
    protected void mergeValues(TaintFrame frame, TaintFrame result, int i) throws DataflowreplacedysisException {
        result.setValue(i, Taint.merge(result.getValue(i), frame.getValue(i)));
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock block, TaintFrame fact) throws DataflowreplacedysisException {
        visitor.setFrameAndLocation(fact, new Location(handle, block));
        visitor.replacedyzeInstruction(handle.getInstruction());
    }

    @Override
    public TaintFrame createFact() {
        return new TaintFrame(methodGen.getMaxLocals());
    }

    /**
     * Initialize the initial state of a TaintFrame.
     * @param fact Initial frame
     */
    @Override
    public void initEntryFact(TaintFrame fact) {
        fact.setValid();
        fact.clearStack();
        boolean inMainMethod = isInMainMethod();
        int numSlots = fact.getNumSlots();
        int numLocals = fact.getNumLocals();
        for (int i = 0; i < numSlots; ++i) {
            Taint value = new Taint(Taint.State.UNKNOWN);
            if (i < numLocals) {
                if (i < parameterStackSize) {
                    if (isTaintedByAnnotation(i - 1)) {
                        value = new Taint(Taint.State.TAINTED);
                    // this would add line number for the first instruction in the method
                    // value.addLocation(new TaintLocation(methodDescriptor, 0), true);
                    } else if (inMainMethod) {
                        if (FindSecBugsGlobalConfig.getInstance().isTaintedMainArgument()) {
                            value = new Taint(Taint.State.TAINTED);
                        } else {
                            value = new Taint(Taint.State.SAFE);
                        }
                    } else {
                        int stackOffset = parameterStackSize - i - 1;
                        value.addParameter(stackOffset);
                    }
                }
                value.setVariableIndex(i);
            }
            fact.setValue(i, value);
        }
    }

    /**
     * @return true if the method is the startup point of a console or gui application
     * ("public static void main(String[] args)"), false otherwise
     */
    private boolean isInMainMethod() {
        return methodDescriptor.isStatic() && "main".equals(methodDescriptor.getName()) && "([Ljava/lang/String;)V".equals(methodDescriptor.getSignature()) && methodGen.getMethod().isPublic();
    }

    /**
     * 添加注解是否被污染
     *  Determine if the slot value is tainted based on added framework annotations.
     *  <hr/>
     *  Example of mapping done:<br/>
     *
     *  Method replacedyzed: "test(String,String,double)V"
     *  For the slot no 2, it look at annotations on the parameter 2.
     *  <pre>
     *           0               1               2               3
     *                                     +++++++++++++
     *   [ double param3 | double param3 | String param2 | String param1 ]
     *  </pre>
     *  <br/>
     *  (Reminder : double and long take two slots for one parameter)
     *
     *  @param slotNo
     *  @return
     */
    private boolean isTaintedByAnnotation(int slotNo) {
        if (slotNo >= 0 && methodDescriptor.hasParameterAnnotations()) {
            int parameter = slotToParameter.get(slotNo);
            Collection<AnnotationValue> annotations = methodDescriptor.getParameterAnnotations(parameter);
            for (AnnotationValue annotation : annotations) {
                if (TAINTED_ANNOTATIONS.contains(annotation.getAnnotationClreplaced().getClreplacedName())) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void meetInto(TaintFrame fact, Edge edge, TaintFrame result) throws DataflowreplacedysisException {
        if (fact.isValid() && edge.isExceptionEdge()) {
            TaintFrame copy = null;
            // creates modifiable copy
            copy = modifyFrame(fact, copy);
            copy.clearStack();
            // do not trust values that are safe just when an exception occurs
            copy.pushValue(new Taint(Taint.State.UNKNOWN));
            fact = copy;
        }
        mergeInto(fact, result);
    }

    /**
     * This method must be called after executing the data flow
     */
    public void finishreplacedysis() {
        visitor.finishreplacedysis();
    }

    /**
     * Compute two values:
     *  <li>The number of values required on the stack for a specific call.</li>
     *  <li>The parameter replacedociation with each slot.</li>
     *
     * <hr/>
     *
     * For exemple : "(I[Ljava/lang/String;Ljava/lang/Object;)V" =>  void a(Integer, String, Object)<br/><br/>
     * Expected Stack prior the method invocation :<br/>
     * <pre>
     * +--------------+
     * | 0: Object    |
     * +--------------+
     * | 1: String    |
     * +--------------+
     * | 2: int       |
     * +--------------+
     * </pre>
     * <hr/>
     *
     * Special note: double and long (primitive types) value take two slots.<br/>
     * For exemple : "(IDJ)V" =>  void a(Integer, Double, Long)
     * <pre>
     * +--------------+
     * | 0: long  pt1 |
     * +--------------+
     * | 1: long  pt2 |
     * +--------------+
     * | 2: double pt1|
     * +--------------+
     * | 3: double pt2|
     * +--------------+
     * | 4: int       |
     * +--------------+
     * </pre>
     *
     * @param signature
     * @param isStatic
     * @return
     */
    private void computeParametersInfo(String signature, boolean isStatic) {
        replacedert signature != null && !signature.isEmpty();
        // static methods does not have reference to this
        int stackSize = isStatic ? 0 : 1;
        GenericSignatureParser parser = new GenericSignatureParser(signature);
        Iterator<String> iterator = parser.parameterSignatureIterator();
        int paramIdx = 0;
        slotToParameter = new ArrayList<Integer>();
        while (iterator.hasNext()) {
            String parameter = iterator.next();
            if (parameter.equals("D") || parameter.equals("J")) {
                // double and long types takes two slots
                stackSize += 2;
                slotToParameter.add(paramIdx);
                slotToParameter.add(paramIdx);
            } else {
                stackSize++;
                slotToParameter.add(paramIdx);
            }
            paramIdx++;
        }
        parameterStackSize = stackSize;
    }

    private static List<String> loadFileContent(String path) {
        BufferedReader stream = null;
        try {
            InputStream in = Taintreplacedysis.clreplaced.getClreplacedLoader().getResourcereplacedtream(path);
            stream = new BufferedReader(new InputStreamReader(in, "utf-8"));
            String line;
            List<String> content = new ArrayList<String>();
            while ((line = stream.readLine()) != null) {
                content.add(line.trim());
            }
            return content;
        } catch (IOException ex) {
            replacedert false : ex.getMessage();
        } finally {
            IO.close(stream);
        }
        return new ArrayList<String>();
    }
}

18 Source : SourceLineAnnotation.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Factory method for creating a source line annotation describing the
 * source line number for a visited instruction.
 *
 * @param clreplacedContext
 *            the ClreplacedContext
 * @param methodGen
 *            the MethodGen object representing the method
 * @param handle
 *            the InstructionHandle containing the visited instruction
 * @return the SourceLineAnnotation, or null if we do not have line number
 *         information for the instruction
 */
@Nonnull
public static SourceLineAnnotation fromVisitedInstruction(ClreplacedContext clreplacedContext, MethodGen methodGen, String sourceFile, @Nonnull InstructionHandle handle) {
    LineNumberTable table = methodGen.getLineNumberTable(methodGen.getConstantPool());
    String clreplacedName = methodGen.getClreplacedName();
    int bytecodeOffset = handle.getPosition();
    if (table == null) {
        return createUnknown(clreplacedName, sourceFile, bytecodeOffset, bytecodeOffset);
    }
    int lineNumber = table.getSourceLine(handle.getPosition());
    return new SourceLineAnnotation(clreplacedName, sourceFile, lineNumber, lineNumber, bytecodeOffset, bytecodeOffset);
}

18 Source : SourceLineAnnotation.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Factory method for creating a source line annotation describing an entire
 * method.
 *
 * @param methodGen
 *            the method being visited
 * @return the SourceLineAnnotation, or null if we do not have line number
 *         information for the method
 */
public static SourceLineAnnotation fromVisitedMethod(MethodGen methodGen, String sourceFile) {
    LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool());
    String clreplacedName = methodGen.getClreplacedName();
    int codeSize = methodGen.getInstructionList().getLength();
    if (lineNumberTable == null) {
        return createUnknown(clreplacedName, sourceFile, 0, codeSize - 1);
    }
    return forEntireMethod(clreplacedName, sourceFile, lineNumberTable, codeSize);
}

18 Source : SourceLineAnnotation.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Factory method for creating a source line annotation describing the
 * source line numbers for a range of instruction in a method.
 *
 * @param clreplacedContext
 *            theClreplacedContext
 * @param methodGen
 *            the method
 * @param start
 *            the start instruction
 * @param end
 *            the end instruction (inclusive)
 */
public static SourceLineAnnotation fromVisitedInstructionRange(ClreplacedContext clreplacedContext, MethodGen methodGen, String sourceFile, InstructionHandle start, InstructionHandle end) {
    LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool());
    String clreplacedName = methodGen.getClreplacedName();
    if (lineNumberTable == null) {
        return createUnknown(clreplacedName, sourceFile, start.getPosition(), end.getPosition());
    }
    int startLine = lineNumberTable.getSourceLine(start.getPosition());
    int endLine = lineNumberTable.getSourceLine(end.getPosition());
    return new SourceLineAnnotation(clreplacedName, sourceFile, startLine, endLine, start.getPosition(), end.getPosition());
}

18 Source : RedundantConditions.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * @param methodGen method
 * @param start instruction to scan
 * @return instruction which consumes value which was on top of stack before start instruction
 * or null if cannot be determined
 */
private InstructionHandle getConsumer(MethodGen methodGen, InstructionHandle start) {
    int depth = 1;
    InstructionHandle cur = start;
    while (cur != null) {
        Instruction inst = cur.getInstruction();
        depth -= inst.consumeStack(methodGen.getConstantPool());
        if (depth <= 0) {
            return cur;
        }
        depth += inst.produceStack(methodGen.getConstantPool());
        if (inst instanceof BranchInstruction) {
            if (inst instanceof GotoInstruction) {
                cur = ((GotoInstruction) inst).getTarget();
                continue;
            }
            if (!(inst instanceof IfInstruction)) {
                return null;
            }
        }
        cur = cur.getNext();
    }
    return null;
}

18 Source : FindSqlInjection.java
with GNU Lesser General Public License v2.1
from spotbugs

@Override
public void visitClreplacedContext(ClreplacedContext clreplacedContext) {
    JavaClreplaced javaClreplaced = clreplacedContext.getJavaClreplaced();
    if (!PreorderVisitor.hasInterestingMethod(javaClreplaced.getConstantPool(), allMethods)) {
        return;
    }
    Method[] methodList = javaClreplaced.getMethods();
    for (Method method : methodList) {
        MethodGen methodGen = clreplacedContext.getMethodGen(method);
        if (methodGen == null) {
            continue;
        }
        try {
            replacedyzeMethod(clreplacedContext, method);
        } catch (DataflowreplacedysisException e) {
            bugReporter.logError("FindSqlInjection caught exception while replacedyzing " + clreplacedContext.getFullyQualifiedMethodName(method), e);
        } catch (CFGBuilderException e) {
            bugReporter.logError("FindSqlInjection caught exception while replacedyzing " + clreplacedContext.getFullyQualifiedMethodName(method), e);
        } catch (RuntimeException e) {
            bugReporter.logError("FindSqlInjection caught exception while replacedyzing " + clreplacedContext.getFullyQualifiedMethodName(method), e);
        }
    }
}

18 Source : StoreDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public StoreDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        return null;
    }
    Storereplacedysis replacedysis = new Storereplacedysis(getDepthFirstSearch(replacedysisCache, descriptor), getConstantPoolGen(replacedysisCache, descriptor.getClreplacedDescriptor()));
    StoreDataflow dataflow = new StoreDataflow(getCFG(replacedysisCache, descriptor), replacedysis);
    dataflow.execute();
    return dataflow;
}

18 Source : LoadDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public LoadDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        return null;
    }
    Loadreplacedysis replacedysis = new Loadreplacedysis(getDepthFirstSearch(replacedysisCache, descriptor), getConstantPoolGen(replacedysisCache, descriptor.getClreplacedDescriptor()));
    LoadDataflow dataflow = new LoadDataflow(getCFG(replacedysisCache, descriptor), replacedysis);
    dataflow.execute();
    return dataflow;
}

18 Source : ConstantDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public ConstantDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        return null;
    }
    Constantreplacedysis replacedysis = new Constantreplacedysis(methodGen, getDepthFirstSearch(replacedysisCache, descriptor));
    ConstantDataflow dataflow = new ConstantDataflow(getCFG(replacedysisCache, descriptor), replacedysis);
    dataflow.execute();
    return dataflow;
}

18 Source : TypeAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * <p>A forward dataflow replacedysis to determine the types of all values in the Java
 * stack frame at all points in a Java method. The values include local
 * variables and values on the Java operand stack.
 * </p>
 * <p>
 * As a side effect, the replacedysis computes the exception set throwable on each
 * exception edge in the CFG. This information can be used to prune infeasible
 * exception edges, and mark exception edges which propagate only implicit
 * exceptions.</p>
 *
 * @author David Hovemeyer
 * @see Dataflow
 * @see edu.umd.cs.findbugs.ba.Dataflowreplacedysis
 * @see TypeFrame
 */
public clreplaced Typereplacedysis extends FrameDataflowreplacedysis<Type, TypeFrame> implements EdgeTypes {

    public static final boolean DEBUG = SystemProperties.getBoolean("ta.debug");

    /**
     * Force computation of accurate exceptions.
     */
    public static final boolean FORCE_ACCURATE_EXCEPTIONS = SystemProperties.getBoolean("ta.accurateExceptions");

    /**
     * Repository of information about thrown exceptions computed for a basic
     * block and its outgoing exception edges. It contains a result TypeFrame,
     * which is used to detect when the exception information needs to be
     * recomputed for the block.
     */
    private clreplaced CachedExceptionSet {

        private final TypeFrame result;

        private final ExceptionSet exceptionSet;

        private final Map<Edge, ExceptionSet> edgeExceptionMap;

        public CachedExceptionSet(TypeFrame result, ExceptionSet exceptionSet) {
            this.result = result;
            this.exceptionSet = exceptionSet;
            this.edgeExceptionMap = new HashMap<>();
        }

        public boolean isUpToDate(TypeFrame result) {
            return this.result.equals(result);
        }

        public ExceptionSet getExceptionSet() {
            return exceptionSet;
        }

        public void setEdgeExceptionSet(Edge edge, ExceptionSet exceptionSet) {
            edgeExceptionMap.put(edge, exceptionSet);
        }

        public ExceptionSet getEdgeExceptionSet(Edge edge) {
            ExceptionSet edgeExceptionSet = edgeExceptionMap.get(edge);
            if (edgeExceptionSet == null) {
                edgeExceptionSet = exceptionSetFactory.createExceptionSet();
                edgeExceptionMap.put(edge, edgeExceptionSet);
            }
            return edgeExceptionSet;
        }
    }

    /**
     * Cached information about an instanceof check.
     */
    static clreplaced InstanceOfCheck {

        final ValueNumber valueNumber;

        final Type type;

        InstanceOfCheck(ValueNumber valueNumber, Type type) {
            this.valueNumber = valueNumber;
            this.type = type;
        }

        /**
         * @return Returns the valueNumber.
         */
        public ValueNumber getValueNumber() {
            return valueNumber;
        }

        /**
         * @return Returns the type.
         */
        public Type getType() {
            return type;
        }
    }

    protected MethodGen methodGen;

    private final Method method;

    protected CFG cfg;

    private final TypeMerger typeMerger;

    private final TypeFrameModelingVisitor visitor;

    private final Map<BasicBlock, CachedExceptionSet> thrownExceptionSetMap;

    private final RepositoryLookupFailureCallback lookupFailureCallback;

    private final ExceptionSetFactory exceptionSetFactory;

    private ValueNumberDataflow valueNumberDataflow;

    private final Map<BasicBlock, InstanceOfCheck> instanceOfCheckMap;

    /**
     * Constructor.
     *
     * @param method
     *            TODO
     * @param methodGen
     *            the MethodGen whose CFG we'll be replacedyzing
     * @param cfg
     *            the control flow graph
     * @param dfs
     *            DepthFirstSearch of the method
     * @param typeMerger
     *            object to merge types
     * @param visitor
     *            a TypeFrameModelingVisitor to use to model the effect of
     *            instructions
     * @param lookupFailureCallback
     *            lookup failure callback
     * @param exceptionSetFactory
     *            factory for creating ExceptionSet objects
     */
    public Typereplacedysis(Method method, MethodGen methodGen, CFG cfg, DepthFirstSearch dfs, TypeMerger typeMerger, TypeFrameModelingVisitor visitor, RepositoryLookupFailureCallback lookupFailureCallback, ExceptionSetFactory exceptionSetFactory) {
        super(dfs);
        this.method = method;
        Code code = method.getCode();
        if (code == null) {
            throw new IllegalArgumentException(method.getName() + " has no code");
        }
        for (Attribute a : code.getAttributes()) {
            if (a instanceof LocalVariableTypeTable) {
                visitor.setLocalTypeTable((LocalVariableTypeTable) a);
            }
        }
        this.methodGen = methodGen;
        this.cfg = cfg;
        this.typeMerger = typeMerger;
        this.visitor = visitor;
        this.thrownExceptionSetMap = new HashMap<>();
        this.lookupFailureCallback = lookupFailureCallback;
        this.exceptionSetFactory = exceptionSetFactory;
        this.instanceOfCheckMap = new HashMap<>();
        if (DEBUG) {
            System.out.println("\n\nreplacedyzing " + methodGen);
        }
    }

    /**
     * Constructor.
     *
     * @param method
     *            TODO
     * @param methodGen
     *            the MethodGen whose CFG we'll be replacedyzing
     * @param cfg
     *            the control flow graph
     * @param dfs
     *            DepthFirstSearch of the method
     * @param typeMerger
     *            object to merge types
     * @param lookupFailureCallback
     *            lookup failure callback
     * @param exceptionSetFactory
     *            factory for creating ExceptionSet objects
     */
    public Typereplacedysis(Method method, MethodGen methodGen, CFG cfg, DepthFirstSearch dfs, TypeMerger typeMerger, RepositoryLookupFailureCallback lookupFailureCallback, ExceptionSetFactory exceptionSetFactory) {
        this(method, methodGen, cfg, dfs, typeMerger, new TypeFrameModelingVisitor(methodGen.getConstantPool(), typeMerger), lookupFailureCallback, exceptionSetFactory);
        if (TypeFrameModelingVisitor.DEBUG) {
            System.out.println(methodGen.getClreplacedName() + "." + methodGen.getName() + " " + methodGen.getSignature());
        }
    }

    /**
     * Constructor which uses StandardTypeMerger.
     *
     * @param method
     *            TODO
     * @param methodGen
     *            the MethodGen whose CFG we'll be replacedyzing
     * @param cfg
     *            the control flow graph
     * @param dfs
     *            DepthFirstSearch of the method
     * @param lookupFailureCallback
     *            callback for Repository lookup failures
     * @param exceptionSetFactory
     *            factory for creating ExceptionSet objects
     */
    public Typereplacedysis(Method method, MethodGen methodGen, CFG cfg, DepthFirstSearch dfs, RepositoryLookupFailureCallback lookupFailureCallback, ExceptionSetFactory exceptionSetFactory) {
        this(method, methodGen, cfg, dfs, new StandardTypeMerger(lookupFailureCallback, exceptionSetFactory), lookupFailureCallback, exceptionSetFactory);
    }

    /**
     * Set the ValueNumberDataflow for the method being replacedyzed. This is
     * optional; if set, it will be used to make instanceof instructions more
     * precise.
     *
     * @param valueNumberDataflow
     *            the ValueNumberDataflow
     */
    public void setValueNumberDataflow(ValueNumberDataflow valueNumberDataflow) {
        this.valueNumberDataflow = valueNumberDataflow;
        this.visitor.setValueNumberDataflow(valueNumberDataflow);
    }

    /**
     * Set the FieldStoreTypeDatabase. This can be used to get more accurate
     * types for values loaded from fields.
     *
     * @param database
     *            the FieldStoreTypeDatabase
     */
    public void setFieldStoreTypeDatabase(FieldStoreTypeDatabase database) {
        visitor.setFieldStoreTypeDatabase(database);
    }

    /**
     * Get the set of exceptions that can be thrown on given edge. This should
     * only be called after the replacedysis completes.
     *
     * @param edge
     *            the Edge
     * @return the ExceptionSet
     */
    public ExceptionSet getEdgeExceptionSet(Edge edge) {
        CachedExceptionSet cachedExceptionSet = thrownExceptionSetMap.get(edge.getSource());
        return cachedExceptionSet.getEdgeExceptionSet(edge);
    }

    @Override
    public TypeFrame createFact() {
        return new TypeFrame(methodGen.getMaxLocals());
    }

    @Override
    public void initEntryFact(TypeFrame result) {
        // Make the frame valid
        result.setValid();
        int slot = 0;
        // Clear the stack slots in the frame
        result.clearStack();
        // Add local for "this" pointer, if present
        if (!methodGen.isStatic()) {
            result.setValue(slot++, ObjectTypeFactory.getInstance(methodGen.getClreplacedName()));
        }
        // [Added: Support for Generics]
        // Get a parser that reads the generic signature of the method and
        // can be used to get the correct GenericObjectType if an argument
        // has a clreplaced type
        Iterator<String> iter = GenericSignatureParser.getGenericSignatureIterator(method);
        // Add locals for parameters.
        // Note that long and double parameters need to be handled
        // specially because they occupy two locals.
        Type[] argumentTypes = methodGen.getArgumentTypes();
        for (Type argType : argumentTypes) {
            // Add special "extra" type for long or double params.
            // These occupy the slot before the "plain" type.
            if (argType.getType() == Const.T_LONG) {
                result.setValue(slot++, TypeFrame.getLongExtraType());
            } else if (argType.getType() == Const.T_DOUBLE) {
                result.setValue(slot++, TypeFrame.getDoubleExtraType());
            }
            // [Added: Support for Generics]
            String s = (iter == null || !iter.hasNext()) ? null : iter.next();
            if (s != null && (argType instanceof ObjectType || argType instanceof ArrayType) && !(argType instanceof ExceptionObjectType)) {
                // replace with a generic version of the type
                try {
                    Type t = GenericUtilities.getType(s);
                    if (t != null) {
                        argType = t;
                    }
                } catch (RuntimeException e) {
                }
            // degrade gracefully
            }
            // Add the plain parameter type.
            result.setValue(slot++, argType);
        }
        // Set remaining locals to BOTTOM; this will cause any
        // uses of them to be flagged
        while (slot < methodGen.getMaxLocals()) {
            result.setValue(slot++, TypeFrame.getBottomType());
        }
    }

    @Override
    public void copy(TypeFrame source, TypeFrame dest) {
        dest.copyFrom(source);
    }

    @Override
    public void makeFactTop(TypeFrame fact) {
        fact.setTop();
    }

    @Override
    public boolean isFactValid(TypeFrame fact) {
        return fact.isValid();
    }

    @Override
    public boolean same(TypeFrame fact1, TypeFrame fact2) {
        return fact1.sameAs(fact2);
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, TypeFrame fact) throws DataflowreplacedysisException {
        visitor.setFrameAndLocation(fact, new Location(handle, basicBlock));
        visitor.replacedyzeInstruction(handle.getInstruction());
    }

    @Override
    public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, TypeFrame start, TypeFrame result) throws DataflowreplacedysisException {
        visitor.startBasicBlock();
        super.transfer(basicBlock, end, start, result);
        // Compute thrown exception types
        computeThrownExceptionTypes(basicBlock, end, result);
        if (DEBUG) {
            System.out.println("After " + basicBlock.getFirstInstruction() + " -> " + basicBlock.getLastInstruction());
            System.out.println("    frame: " + result);
        }
        // If this block ends with an instanceof check,
        // update the cached information about it.
        instanceOfCheckMap.remove(basicBlock);
        if (visitor.isInstanceOfFollowedByBranch()) {
            InstanceOfCheck check = new InstanceOfCheck(visitor.getInstanceOfValueNumber(), visitor.getInstanceOfType());
            instanceOfCheckMap.put(basicBlock, check);
        }
    }

    private void computeThrownExceptionTypes(BasicBlock basicBlock, @CheckForNull InstructionHandle end, TypeFrame result) throws DataflowreplacedysisException {
        // Do nothing if we're not computing propagated exceptions
        if (!(FORCE_ACCURATE_EXCEPTIONS || replacedysisContext.currentreplacedysisContext().getBoolProperty(replacedysisFeatures.ACCURATE_EXCEPTIONS))) {
            return;
        }
        // Also, nothing to do if the block is not an exception thrower
        if (!basicBlock.isExceptionThrower()) {
            return;
        }
        // If cached results are up to date, don't recompute.
        CachedExceptionSet cachedExceptionSet = getCachedExceptionSet(basicBlock);
        if (cachedExceptionSet.isUpToDate(result)) {
            return;
        }
        // Figure out what exceptions can be thrown out
        // of the basic block, and mark each exception edge
        // with the set of exceptions which can be propagated
        // along the edge.
        int exceptionEdgeCount = 0;
        Edge lastExceptionEdge = null;
        for (Iterator<Edge> i = cfg.outgoingEdgeIterator(basicBlock); i.hasNext(); ) {
            Edge e = i.next();
            if (e.isExceptionEdge()) {
                exceptionEdgeCount++;
                lastExceptionEdge = e;
            }
        }
        if (exceptionEdgeCount == 0) {
            // System.out.println("Shouldn't all blocks have an exception edge");
            return;
        }
        // Compute exceptions that can be thrown by the
        // basic block.
        cachedExceptionSet = computeBlockExceptionSet(basicBlock, result);
        if (exceptionEdgeCount == 1) {
            cachedExceptionSet.setEdgeExceptionSet(lastExceptionEdge, cachedExceptionSet.getExceptionSet());
            return;
        }
        // For each outgoing exception edge, compute exceptions
        // that can be thrown. This replacedumes that the exception
        // edges are enumerated in decreasing order of priority.
        // In the process, this will remove exceptions from
        // the thrown exception set.
        ExceptionSet thrownExceptionSet = cachedExceptionSet.getExceptionSet();
        if (!thrownExceptionSet.isEmpty()) {
            thrownExceptionSet = thrownExceptionSet.duplicate();
        }
        for (Iterator<Edge> i = cfg.outgoingEdgeIterator(basicBlock); i.hasNext(); ) {
            Edge edge = i.next();
            if (edge.isExceptionEdge()) {
                cachedExceptionSet.setEdgeExceptionSet(edge, computeEdgeExceptionSet(edge, thrownExceptionSet));
            }
        }
    }

    @Override
    public void meetInto(TypeFrame fact, Edge edge, TypeFrame result) throws DataflowreplacedysisException {
        BasicBlock basicBlock = edge.getTarget();
        if (fact.isValid()) {
            TypeFrame tmpFact = null;
            // Handling an exception?
            if (basicBlock.isExceptionHandler()) {
                tmpFact = modifyFrame(fact, null);
                // Special case: when merging predecessor facts for entry to
                // an exception handler, we clear the stack and push a
                // single entry for the exception object. That way, the locals
                // can still be merged.
                CodeExceptionGen exceptionGen = basicBlock.getExceptionGen();
                tmpFact.clearStack();
                // Determine the type of exception(s) caught.
                Type catchType = null;
                if (FORCE_ACCURATE_EXCEPTIONS || replacedysisContext.currentreplacedysisContext().getBoolProperty(replacedysisFeatures.ACCURATE_EXCEPTIONS)) {
                    try {
                        // Ideally, the exceptions that can be propagated
                        // on this edge has already been computed.
                        CachedExceptionSet cachedExceptionSet = getCachedExceptionSet(edge.getSource());
                        ExceptionSet edgeExceptionSet = cachedExceptionSet.getEdgeExceptionSet(edge);
                        if (!edgeExceptionSet.isEmpty()) {
                            // System.out.println("Using computed edge exception set!");
                            catchType = ExceptionObjectType.fromExceptionSet(edgeExceptionSet);
                        }
                    } catch (ClreplacedNotFoundException e) {
                        lookupFailureCallback.reportMissingClreplaced(e);
                    }
                }
                if (catchType == null) {
                    // No information about propagated exceptions, so
                    // pick a type conservatively using the handler catch type.
                    catchType = exceptionGen.getCatchType();
                    if (catchType == null) {
                        // handle catches anything
                        catchType = Type.THROWABLE;
                    // throwable
                    }
                }
                tmpFact.pushValue(catchType);
            }
            // See if we can make some types more precise due to
            // a successful instanceof check in the source block.
            if (valueNumberDataflow != null) {
                tmpFact = handleInstanceOfBranch(fact, tmpFact, edge);
            }
            if (tmpFact != null) {
                fact = tmpFact;
            }
        }
        mergeInto(fact, result);
    }

    private TypeFrame handleInstanceOfBranch(TypeFrame fact, TypeFrame tmpFact, Edge edge) {
        InstanceOfCheck check = instanceOfCheckMap.get(edge.getSource());
        if (check == null) {
            // System.out.println("no instanceof check for block " +
            // edge.getSource().getId());
            return tmpFact;
        }
        if (check.getValueNumber() == null) {
            // System.out.println("instanceof check for block " +
            // edge.getSource().getId() + " has no value number");
            return tmpFact;
        }
        ValueNumber instanceOfValueNumber = check.getValueNumber();
        ValueNumberFrame vnaFrame = valueNumberDataflow.getStartFact(edge.getTarget());
        if (!vnaFrame.isValid()) {
            return tmpFact;
        }
        Type instanceOfType = check.getType();
        if (!(instanceOfType instanceof ReferenceType)) {
            return tmpFact;
        }
        short branchOpcode = edge.getSource().getLastInstruction().getInstruction().getOpcode();
        int edgeType = edge.getType();
        int numSlots = Math.min(fact.getNumSlots(), vnaFrame.getNumSlots());
        if ((edgeType == EdgeTypes.IFCMP_EDGE && (branchOpcode == Const.IFNE || branchOpcode == Const.IFGT || branchOpcode == Const.IFNULL)) || (edgeType == EdgeTypes.FALL_THROUGH_EDGE && (branchOpcode == Const.IFEQ || branchOpcode == Const.IFLE || branchOpcode == Const.IFNONNULL))) {
            // System.out.println("Successful check on edge " + edge);
            // Successful instanceof check.
            for (int i = 0; i < numSlots; ++i) {
                if (!vnaFrame.getValue(i).equals(instanceOfValueNumber)) {
                    continue;
                }
                Type checkedType = fact.getValue(i);
                if (!(checkedType instanceof ReferenceType)) {
                    continue;
                }
                // Only refine the type if the cast is feasible: i.e., a
                // downcast.
                // Otherwise, just set it to TOP.
                try {
                    boolean guaranteed = Hierarchy.isSubtype((ReferenceType) checkedType, (ReferenceType) instanceOfType);
                    if (guaranteed) {
                        continue;
                    }
                    boolean feasibleCheck = instanceOfType.equals(NullType.instance()) || Hierarchy.isSubtype((ReferenceType) instanceOfType, (ReferenceType) checkedType);
                    if (!feasibleCheck && instanceOfType instanceof ObjectType && checkedType instanceof ObjectType) {
                        double v = replacedyze.deepInstanceOf(((ObjectType) instanceOfType).getClreplacedName(), ((ObjectType) checkedType).getClreplacedName());
                        if (v > 0.0) {
                            feasibleCheck = true;
                        }
                    }
                    tmpFact = modifyFrame(fact, tmpFact);
                    if (feasibleCheck) {
                        tmpFact.setValue(i, instanceOfType);
                    } else {
                        tmpFact.setTop();
                        return tmpFact;
                    }
                } catch (ClreplacedNotFoundException e) {
                    lookupFailureCallback.reportMissingClreplaced(e);
                    return tmpFact;
                }
            }
        } else if (!instanceOfType.equals(NullType.instance())) {
            for (int i = 0; i < numSlots; ++i) {
                if (!vnaFrame.getValue(i).equals(instanceOfValueNumber)) {
                    continue;
                }
                Type checkedType = fact.getValue(i);
                if (!(checkedType instanceof ReferenceType)) {
                    continue;
                }
                try {
                    boolean guaranteed = Hierarchy.isSubtype((ReferenceType) checkedType, (ReferenceType) instanceOfType);
                    if (!guaranteed) {
                        continue;
                    }
                    tmpFact = modifyFrame(fact, tmpFact);
                    tmpFact.setTop();
                    return tmpFact;
                } catch (ClreplacedNotFoundException e) {
                    lookupFailureCallback.reportMissingClreplaced(e);
                    return tmpFact;
                }
            }
        }
        return tmpFact;
    }

    @Override
    protected void mergeValues(TypeFrame otherFrame, TypeFrame resultFrame, int slot) throws DataflowreplacedysisException {
        Type type2 = resultFrame.getValue(slot);
        Type type1 = otherFrame.getValue(slot);
        Type value = typeMerger.mergeTypes(type2, type1);
        resultFrame.setValue(slot, value);
        // Result type is exact IFF types are identical and both are exact
        boolean typesAreIdentical = type1.equals(type2);
        boolean bothExact = resultFrame.isExact(slot) && otherFrame.isExact(slot);
        resultFrame.setExact(slot, typesAreIdentical && bothExact);
    }

    /**
     * Get the cached set of exceptions that can be thrown from given basic
     * block. If this information hasn't been computed yet, then an empty
     * exception set is returned.
     *
     * @param basicBlock
     *            the block to get the cached exception set for
     * @return the CachedExceptionSet for the block
     */
    private CachedExceptionSet getCachedExceptionSet(BasicBlock basicBlock) {
        CachedExceptionSet cachedExceptionSet = thrownExceptionSetMap.get(basicBlock);
        if (cachedExceptionSet == null) {
            // When creating the cached exception type set for the first time:
            // - the block result is set to TOP, so it won't match
            // any block result that has actually been computed
            // using the replacedysis transfer function
            // - the exception set is created as empty (which makes it
            // return TOP as its common superclreplaced)
            TypeFrame top = createFact();
            makeFactTop(top);
            cachedExceptionSet = new CachedExceptionSet(top, exceptionSetFactory.createExceptionSet());
            thrownExceptionSetMap.put(basicBlock, cachedExceptionSet);
        }
        return cachedExceptionSet;
    }

    /**
     * Compute the set of exceptions that can be thrown from the given basic
     * block. This should only be called if the existing cached exception set is
     * out of date.
     *
     * @param basicBlock
     *            the basic block
     * @param result
     *            the result fact for the block; this is used to determine
     *            whether or not the cached exception set is up to date
     * @return the cached exception set for the block
     */
    private CachedExceptionSet computeBlockExceptionSet(BasicBlock basicBlock, TypeFrame result) throws DataflowreplacedysisException {
        ExceptionSet exceptionSet = computeThrownExceptionTypes(basicBlock);
        TypeFrame copyOfResult = createFact();
        copy(result, copyOfResult);
        CachedExceptionSet cachedExceptionSet = new CachedExceptionSet(copyOfResult, exceptionSet);
        thrownExceptionSetMap.put(basicBlock, cachedExceptionSet);
        return cachedExceptionSet;
    }

    /**
     * Based on the set of exceptions that can be thrown from the source basic
     * block, compute the set of exceptions that can propagate along given
     * exception edge. This method should be called for each outgoing exception
     * edge in sequence, so the caught exceptions can be removed from the thrown
     * exception set as needed.
     *
     * @param edge
     *            the exception edge
     * @param thrownExceptionSet
     *            current set of exceptions that can be thrown, taking earlier
     *            (higher priority) exception edges into account
     * @return the set of exceptions that can propagate along this edge
     */
    private ExceptionSet computeEdgeExceptionSet(Edge edge, ExceptionSet thrownExceptionSet) {
        if (thrownExceptionSet.isEmpty()) {
            return thrownExceptionSet;
        }
        ExceptionSet result = exceptionSetFactory.createExceptionSet();
        if (edge.getType() == UNHANDLED_EXCEPTION_EDGE) {
            // The unhandled exception edge always comes
            // after all of the handled exception edges.
            result.addAll(thrownExceptionSet);
            thrownExceptionSet.clear();
            return result;
        }
        BasicBlock handlerBlock = edge.getTarget();
        CodeExceptionGen handler = handlerBlock.getExceptionGen();
        ObjectType catchType = handler.getCatchType();
        if (Hierarchy.isUniversalExceptionHandler(catchType)) {
            result.addAll(thrownExceptionSet);
            thrownExceptionSet.clear();
        } else {
            // Go through the set of thrown exceptions.
            // Any that will DEFINITELY be caught be this handler, remove.
            // Any that MIGHT be caught, but won't definitely be caught,
            // remain.
            for (ExceptionSet.ThrownExceptionIterator i = thrownExceptionSet.iterator(); i.hasNext(); ) {
                // ThrownException thrownException = i.next();
                ObjectType thrownType = i.next();
                boolean explicit = i.isExplicit();
                if (DEBUG) {
                    System.out.println("\texception type " + thrownType + ", catch type " + catchType);
                }
                try {
                    if (Hierarchy.isSubtype(thrownType, catchType)) {
                        // Exception can be thrown along this edge
                        result.add(thrownType, explicit);
                        // And it will definitely be caught
                        i.remove();
                        if (DEBUG) {
                            System.out.println("\tException is subtype of catch type: " + "will definitely catch");
                        }
                    } else if (Hierarchy.isSubtype(catchType, thrownType)) {
                        // Exception possibly thrown along this edge
                        result.add(thrownType, explicit);
                        if (DEBUG) {
                            System.out.println("\tException is supertype of catch type: " + "might catch");
                        }
                    }
                } catch (ClreplacedNotFoundException e) {
                    // As a special case, if a clreplaced hierarchy lookup
                    // fails, then we will conservatively replacedume that the
                    // exception in question CAN, but WON'T NECESSARILY
                    // be caught by the handler.
                    replacedysisContext.reportMissingClreplaced(e);
                    result.add(thrownType, explicit);
                }
            }
        }
        return result;
    }

    /**
     * Compute the set of exception types that can be thrown by given basic
     * block.
     *
     * @param basicBlock
     *            the basic block
     * @return the set of exceptions that can be thrown by the block
     */
    private ExceptionSet computeThrownExceptionTypes(BasicBlock basicBlock) throws DataflowreplacedysisException {
        ExceptionSet exceptionTypeSet = exceptionSetFactory.createExceptionSet();
        InstructionHandle pei = basicBlock.getExceptionThrower();
        Instruction ins = pei.getInstruction();
        // Get the exceptions that BCEL knows about.
        // Note that all of these are unchecked.
        ExceptionThrower exceptionThrower = (ExceptionThrower) ins;
        Clreplaced<?>[] exceptionList = exceptionThrower.getExceptions();
        for (Clreplaced<?> aExceptionList : exceptionList) {
            exceptionTypeSet.addImplicit(ObjectTypeFactory.getInstance(aExceptionList.getName()));
        }
        // replacedume that an Error may be thrown by any instruction.
        exceptionTypeSet.addImplicit(Hierarchy.ERROR_TYPE);
        if (ins instanceof ATHROW) {
            // For ATHROW instructions, we generate *two* blocks
            // for which the ATHROW is an exception thrower.
            // 
            // - The first, empty basic block, does the null check
            // - The second block, which actually contains the ATHROW,
            // throws the object on the top of the operand stack
            // 
            // We make a special case of the block containing the ATHROW,
            // by removing all of the implicit exceptions,
            // and using type information to figure out what is thrown.
            if (basicBlock.containsInstruction(pei)) {
                // This is the actual ATHROW, not the null check
                // and implicit exceptions.
                exceptionTypeSet.clear();
                // The frame containing the thrown value is the start fact
                // for the block, because ATHROW is guaranteed to be
                // the only instruction in the block.
                TypeFrame frame = getStartFact(basicBlock);
                // Check whether or not the frame is valid.
                // Sun's javac sometimes emits unreachable code.
                // For example, it will emit code that follows a JSR
                // subroutine call that never returns.
                // If the frame is invalid, then we can just make
                // a conservative replacedumption that anything could be
                // thrown at this ATHROW.
                if (!frame.isValid()) {
                    exceptionTypeSet.addExplicit(Type.THROWABLE);
                } else if (frame.getStackDepth() == 0) {
                    throw new IllegalStateException("empty stack " + " thrown by " + pei + " in " + SignatureConverter.convertMethodSignature(methodGen));
                } else {
                    Type throwType = frame.getTopValue();
                    if (throwType instanceof ObjectType) {
                        exceptionTypeSet.addExplicit((ObjectType) throwType);
                    } else {
                        // Not sure what is being thrown here.
                        // Be conservative.
                        if (DEBUG) {
                            System.out.println("Non object type " + throwType + " thrown by " + pei + " in " + SignatureConverter.convertMethodSignature(methodGen));
                        }
                        exceptionTypeSet.addExplicit(Type.THROWABLE);
                    }
                }
            }
        }
        // If it's an InvokeInstruction, add declared exceptions and
        // RuntimeException
        if (ins instanceof InvokeInstruction) {
            ConstantPoolGen cpg = methodGen.getConstantPool();
            InvokeInstruction inv = (InvokeInstruction) ins;
            ObjectType[] declaredExceptionList = Hierarchy2.findDeclaredExceptions(inv, cpg);
            if (declaredExceptionList == null) {
                // Couldn't find declared exceptions,
                // so conservatively replacedume it could thrown any checked
                // exception.
                if (DEBUG) {
                    System.out.println("Couldn't find declared exceptions for " + SignatureConverter.convertMethodSignature(inv, cpg));
                }
                exceptionTypeSet.addExplicit(Hierarchy.EXCEPTION_TYPE);
            } else {
                for (ObjectType aDeclaredExceptionList : declaredExceptionList) {
                    exceptionTypeSet.addExplicit(aDeclaredExceptionList);
                }
            }
            exceptionTypeSet.addImplicit(Hierarchy.RUNTIME_EXCEPTION_TYPE);
        }
        if (DEBUG) {
            System.out.println(pei + " can throw " + exceptionTypeSet);
        }
        return exceptionTypeSet;
    }

    @Override
    public String toString() {
        return this.getClreplaced().getSimpleName() + "(" + methodGen.getClreplacedName() + "." + methodGen.getMethod().getName() + methodGen.getMethod().getSignature() + ")";
    }

    public boolean isImpliedByGenericTypes(ReferenceType t) {
        return visitor.isImpliedByGenericTypes(t);
    }
    // public static void main(String[] argv) throws Exception {
    // if (argv.length != 1) {
    // System.err.println("Usage: " + Typereplacedysis.clreplaced.getName() +
    // " <clreplaced file>");
    // System.exit(1);
    // }
    // 
    // DataflowTestDriver<TypeFrame, Typereplacedysis> driver = new
    // DataflowTestDriver<TypeFrame, Typereplacedysis>() {
    // @Override
    // public Dataflow<TypeFrame, Typereplacedysis> createDataflow(ClreplacedContext
    // clreplacedContext, Method method)
    // throws CFGBuilderException, DataflowreplacedysisException {
    // return clreplacedContext.getTypeDataflow(method);
    // }
    // };
    // 
    // driver.execute(argv[0]);
    // }
}

18 Source : IsNullValueAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * A dataflow replacedysis to detect potential null pointer dereferences.
 *
 * @author David Hovemeyer
 * @see IsNullValue
 * @see IsNullValueFrame
 * @see IsNullValueFrameModelingVisitor
 */
public clreplaced IsNullValuereplacedysis extends FrameDataflowreplacedysis<IsNullValue, IsNullValueFrame> implements EdgeTypes, IsNullValuereplacedysisFeatures {

    static final boolean DEBUG = SystemProperties.getBoolean("inva.debug");

    static {
        if (DEBUG) {
            System.out.println("inva.debug enabled");
        }
    }

    private final MethodGen methodGen;

    private final IsNullValueFrameModelingVisitor visitor;

    private final ValueNumberDataflow vnaDataflow;

    private final CFG cfg;

    private final Set<LocationWhereValueBecomesNull> locationWhereValueBecomesNullSet;

    private final boolean trackValueNumbers;

    private IsNullValueFrame lastFrame;

    private IsNullValueFrame instanceOfFrame;

    private IsNullValueFrame cachedEntryFact;

    private JavaClreplacedAndMethod clreplacedAndMethod;

    @CheckForNull
    private final PointerEqualityCheck pointerEqualityCheck;

    public IsNullValuereplacedysis(MethodDescriptor descriptor, MethodGen methodGen, CFG cfg, ValueNumberDataflow vnaDataflow, TypeDataflow typeDataflow, DepthFirstSearch dfs, replacedertionMethods replacedertionMethods) {
        super(dfs);
        this.trackValueNumbers = replacedysisContext.currentreplacedysisContext().getBoolProperty(replacedysisFeatures.TRACK_VALUE_NUMBERS_IN_NULL_POINTER_replacedYSIS);
        this.methodGen = methodGen;
        this.visitor = new IsNullValueFrameModelingVisitor(methodGen.getConstantPool(), replacedertionMethods, vnaDataflow, typeDataflow, trackValueNumbers);
        this.vnaDataflow = vnaDataflow;
        this.cfg = cfg;
        this.locationWhereValueBecomesNullSet = new HashSet<>();
        this.pointerEqualityCheck = getForPointerEqualityCheck(cfg, vnaDataflow);
        if (DEBUG) {
            System.out.println("IsNullValuereplacedysis for " + methodGen.getClreplacedName() + "." + methodGen.getName() + " : " + methodGen.getSignature());
        }
    }

    enum PointerEqualityCheckState {

        INIT,
        START,
        SAW1,
        SAW2,
        IFEQUAL,
        IFNOTEQUAL
    }

    @CheckForNull
    public static PointerEqualityCheck getForPointerEqualityCheck(CFG cfg, ValueNumberDataflow vna) {
        PointerEqualityCheckState state = PointerEqualityCheckState.INIT;
        int target = Integer.MAX_VALUE;
        Location test = null;
        for (Location loc : cfg.orderedLocations()) {
            Instruction ins = loc.getHandle().getInstruction();
            switch(state) {
                case INIT:
                    replacedert ins instanceof org.apache.bcel.generic.NOP;
                    state = PointerEqualityCheckState.START;
                    break;
                case START:
                    if (ins instanceof ALOAD) {
                        state = PointerEqualityCheckState.SAW1;
                    } else {
                        return null;
                    }
                    break;
                case SAW1:
                    if (ins instanceof ALOAD) {
                        state = PointerEqualityCheckState.SAW2;
                    } else {
                        return null;
                    }
                    break;
                case SAW2:
                    if (ins instanceof IF_ACMPNE) {
                        state = PointerEqualityCheckState.IFEQUAL;
                        target = ((IF_ACMPNE) ins).getIndex() + loc.getHandle().getPosition();
                        test = loc;
                    } else {
                        return null;
                    }
                    break;
                case IFEQUAL:
                    if (ins instanceof org.apache.bcel.generic.ReturnInstruction || ins instanceof ATHROW) {
                        state = PointerEqualityCheckState.IFNOTEQUAL;
                    } else if (ins instanceof org.apache.bcel.generic.BranchInstruction) {
                        return null;
                    }
                    break;
                case IFNOTEQUAL:
                    if (loc.getHandle().getPosition() == target) {
                        try {
                            ValueNumberFrame vnaFrame = vna.getFactAtLocation(test);
                            return new PointerEqualityCheck(vnaFrame.getStackValue(0), vnaFrame.getStackValue(1), target);
                        } catch (DataflowreplacedysisException e) {
                            return null;
                        }
                    } else {
                        return null;
                    }
            }
        }
        return null;
    }

    @CheckForNull
    private ValueNumber getKnownNonnullDueToPointerDisequality(ValueNumber knownNull, int pc) {
        if (pointerEqualityCheck == null || pc < pointerEqualityCheck.firstValuePC) {
            return null;
        }
        if (pointerEqualityCheck.reg1.equals(knownNull)) {
            return pointerEqualityCheck.reg2;
        }
        if (pointerEqualityCheck.reg2.equals(knownNull)) {
            return pointerEqualityCheck.reg1;
        }
        return null;
    }

    public static clreplaced PointerEqualityCheck {

        final ValueNumber reg1, reg2;

        final int firstValuePC;

        public PointerEqualityCheck(ValueNumber reg1, ValueNumber reg2, int firstValuePC) {
            this.reg1 = reg1;
            this.reg2 = reg2;
            this.firstValuePC = firstValuePC;
        }
    }

    public void setClreplacedAndMethod(JavaClreplacedAndMethod clreplacedAndMethod) {
        this.clreplacedAndMethod = clreplacedAndMethod;
    }

    public JavaClreplacedAndMethod getClreplacedAndMethod() {
        return clreplacedAndMethod;
    }

    @Override
    public IsNullValueFrame createFact() {
        return new IsNullValueFrame(methodGen.getMaxLocals(), trackValueNumbers);
    }

    @Override
    public void initEntryFact(IsNullValueFrame result) {
        if (cachedEntryFact == null) {
            cachedEntryFact = createFact();
            cachedEntryFact.setValid();
            int numLocals = methodGen.getMaxLocals();
            boolean instanceMethod = !methodGen.isStatic();
            XMethod xm = XFactory.createXMethod(methodGen.getClreplacedName(), methodGen.getName(), methodGen.getSignature(), methodGen.isStatic());
            INullnessAnnotationDatabase db = replacedysisContext.currentreplacedysisContext().getNullnessAnnotationDatabase();
            int paramShift = instanceMethod ? 1 : 0;
            Type[] argumentTypes = methodGen.getArgumentTypes();
            for (int i = 0; i < numLocals; ++i) {
                cachedEntryFact.setValue(i, IsNullValue.nonReportingNotNullValue());
            }
            if (paramShift == 1) {
                cachedEntryFact.setValue(0, IsNullValue.nonNullValue());
            }
            int slot = paramShift;
            for (int paramIndex = 0; paramIndex < argumentTypes.length; paramIndex++) {
                IsNullValue value;
                XMethodParameter methodParameter = new XMethodParameter(xm, paramIndex);
                NullnessAnnotation n = db.getResolvedAnnotation(methodParameter, false);
                if (n == NullnessAnnotation.CHECK_FOR_NULL) {
                    // Parameter declared @CheckForNull
                    value = IsNullValue.parameterMarkedAsMightBeNull(methodParameter);
                } else if (n == NullnessAnnotation.NONNULL) {
                    // Parameter declared @NonNull
                    // TODO: label this so we don't report defensive programming
                    // value = false ? IsNullValue.nonNullValue()  : IsNullValue.parameterMarkedAsNonnull(methodParameter);
                    value = IsNullValue.parameterMarkedAsNonnull(methodParameter);
                } else {
                    // Don't know; use default value, normally non-reporting
                    // nonnull
                    value = IsNullValue.nonReportingNotNullValue();
                }
                cachedEntryFact.setValue(slot, value);
                slot += argumentTypes[paramIndex].getSize();
            }
        }
        copy(cachedEntryFact, result);
    }

    @Override
    public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, IsNullValueFrame start, IsNullValueFrame result) throws DataflowreplacedysisException {
        startTransfer();
        super.transfer(basicBlock, end, start, result);
        endTransfer(basicBlock, end, result);
        if (end == null) {
            ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(Location.getLastLocation(basicBlock));
            // purge stale information
            if (!vnaFrameAfter.isTop()) {
                result.cleanStaleKnowledge(vnaFrameAfter);
            }
        }
    }

    public void startTransfer() {
        lastFrame = null;
        instanceOfFrame = null;
    }

    public void endTransfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, IsNullValueFrame result) throws DataflowreplacedysisException {
        // Determine if this basic block ends in a redundant branch.
        if (end == null) {
            if (lastFrame == null) {
                result.setDecision(null);
            } else {
                IsNullConditionDecision decision = getDecision(basicBlock, lastFrame);
                result.setDecision(decision);
            }
        }
        lastFrame = null;
        instanceOfFrame = null;
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, IsNullValueFrame fact) throws DataflowreplacedysisException {
        if (!fact.isValid()) {
            return;
        }
        // If this is the last instruction in the block,
        // save the result immediately before the instruction.
        if (handle == basicBlock.getLastInstruction()) {
            lastFrame = createFact();
            lastFrame.copyFrom(fact);
        }
        if (handle.getInstruction().getOpcode() == Const.INSTANCEOF) {
            instanceOfFrame = createFact();
            instanceOfFrame.copyFrom(fact);
        }
        // Model the instruction
        visitor.setFrameAndLocation(fact, new Location(handle, basicBlock));
        Instruction ins = handle.getInstruction();
        visitor.replacedyzeInstruction(ins);
        if (!fact.isValid()) {
            return;
        }
        // Special case:
        // The instruction may have produced previously seen values
        // about which new is-null information is known.
        // If any other instances of the produced values exist,
        // update their is-null information.
        // Also, make a note of any newly-produced null values.
        int numProduced = ins.produceStack(methodGen.getConstantPool());
        if (numProduced == Const.UNPREDICTABLE) {
            throw new DataflowreplacedysisException("Unpredictable stack production", methodGen, handle);
        }
        int start = fact.getNumSlots() - numProduced;
        Location location = new Location(handle, basicBlock);
        ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(location);
        if (!vnaFrameAfter.isValid()) {
            replacedert false : "Invalid VNA after location " + location + " in " + SignatureConverter.convertMethodSignature(methodGen);
            return;
        }
        for (int i = start; i < fact.getNumSlots(); ++i) {
            ValueNumber value = vnaFrameAfter.getValue(i);
            IsNullValue isNullValue = fact.getValue(i);
            for (int j = 0; j < start; ++j) {
                ValueNumber otherValue = vnaFrameAfter.getValue(j);
                if (value.equals(otherValue)) {
                    // Same value is in both slots.
                    // Update the is-null information to match
                    // the new information.
                    fact.setValue(j, isNullValue);
                }
            }
        }
        if (visitor.getSlotContainingNewNullValue() >= 0) {
            ValueNumber newNullValue = vnaFrameAfter.getValue(visitor.getSlotContainingNewNullValue());
            addLocationWhereValueBecomesNull(new // ,
            LocationWhereValueBecomesNull(// ,
            location, // ,
            newNullValue));
        }
    }

    private static final BitSet nullComparisonInstructionSet = new BitSet();

    static {
        nullComparisonInstructionSet.set(Const.IFNULL);
        nullComparisonInstructionSet.set(Const.IFNONNULL);
        nullComparisonInstructionSet.set(Const.IF_ACMPEQ);
        nullComparisonInstructionSet.set(Const.IF_ACMPNE);
    }

    @Override
    public void meetInto(IsNullValueFrame fact, Edge edge, IsNullValueFrame result) throws DataflowreplacedysisException {
        meetInto(fact, edge, result, true);
    }

    public void meetInto(IsNullValueFrame fact, Edge edge, IsNullValueFrame result, boolean propagatePhiNodeInformation) throws DataflowreplacedysisException {
        if (fact.isValid()) {
            IsNullValueFrame tmpFact = null;
            if (!NO_SPLIT_DOWNGRADE_NSP) {
                // Downgrade NSP to DNR on non-exception control splits
                if (!edge.isExceptionEdge() && cfg.getNumNonExceptionSucessors(edge.getSource()) > 1) {
                    tmpFact = modifyFrame(fact, null);
                    tmpFact.downgradeOnControlSplit();
                }
            }
            if (!NO_SWITCH_DEFAULT_AS_EXCEPTION) {
                if (edge.getType() == SWITCH_DEFAULT_EDGE) {
                    tmpFact = modifyFrame(fact, tmpFact);
                    tmpFact.toExceptionValues();
                }
            }
            final BasicBlock destBlock = edge.getTarget();
            if (destBlock.isExceptionHandler()) {
                // Exception handler - clear stack and push a non-null value
                // to represent the exception.
                tmpFact = modifyFrame(fact, tmpFact);
                tmpFact.clearStack();
                // Downgrade NULL and NSP to DNR if the handler is for
                // CloneNotSupportedException or InterruptedException
                CodeExceptionGen handler = destBlock.getExceptionGen();
                ObjectType catchType = handler.getCatchType();
                if (catchType != null) {
                    String catchClreplaced = catchType.getClreplacedName();
                    if ("java.lang.CloneNotSupportedException".equals(catchClreplaced) || "java.lang.InterruptedException".equals(catchClreplaced)) {
                        for (int i = 0; i < tmpFact.getNumSlots(); ++i) {
                            IsNullValue value = tmpFact.getValue(i);
                            if (value.isDefinitelyNull() || value.isNullOnSomePath()) {
                                tmpFact.setValue(i, IsNullValue.nullOnComplexPathValue());
                            }
                        }
                    }
                }
                // Mark all values as having occurred on an exception path
                tmpFact.toExceptionValues();
                // Push the exception value
                tmpFact.pushValue(IsNullValue.nonNullValue());
            } else {
                final int edgeType = edge.getType();
                final BasicBlock sourceBlock = edge.getSource();
                final BasicBlock targetBlock = edge.getTarget();
                final ValueNumberFrame targetVnaFrame = vnaDataflow.getStartFact(destBlock);
                final ValueNumberFrame sourceVnaFrame = vnaDataflow.getResultFact(sourceBlock);
                replacedert targetVnaFrame != null;
                // Determine if the edge conveys any information about the
                // null/non-null status of operands in the incoming frame.
                if (edgeType == IFCMP_EDGE || edgeType == FALL_THROUGH_EDGE) {
                    IsNullValueFrame resultFact = getResultFact(sourceBlock);
                    IsNullConditionDecision decision = resultFact.getDecision();
                    if (decision != null) {
                        if (!decision.isEdgeFeasible(edgeType)) {
                            // The incoming edge is infeasible; just use TOP
                            // as the start fact for this block.
                            tmpFact = createFact();
                            tmpFact.setTop();
                        } else {
                            ValueNumber valueTested = decision.getValue();
                            if (valueTested != null) {
                                // A value has been determined for this edge.
                                // Use the value to update the is-null
                                // information in
                                // the start fact for this block.
                                if (DEBUG) {
                                    System.out.println("Updating edge information for " + valueTested);
                                }
                                final Location atIf = new Location(sourceBlock.getLastInstruction(), sourceBlock);
                                final ValueNumberFrame prevVnaFrame = vnaDataflow.getFactAtLocation(atIf);
                                IsNullValue decisionValue = decision.getDecision(edgeType);
                                if (decisionValue != null) {
                                    if (DEBUG) {
                                        System.out.println("Set decision information");
                                        System.out.println("  " + valueTested + " becomes " + decisionValue);
                                        System.out.println("  at " + targetBlock.getFirstInstruction().getPosition());
                                        System.out.println("  prev available loads: " + prevVnaFrame.availableLoadMapreplacedtring());
                                        System.out.println("  target available loads: " + targetVnaFrame.availableLoadMapreplacedtring());
                                    }
                                    tmpFact = replaceValues(fact, tmpFact, valueTested, prevVnaFrame, targetVnaFrame, decisionValue);
                                    if (decisionValue.isDefinitelyNull()) {
                                        // Make a note of the value that has
                                        // become null
                                        // due to the if comparison.
                                        addLocationWhereValueBecomesNull(new LocationWhereValueBecomesNull(atIf, valueTested));
                                        ValueNumber knownNonnull = getKnownNonnullDueToPointerDisequality(valueTested, atIf.getHandle().getPosition());
                                        if (knownNonnull != null) {
                                            tmpFact = replaceValues(fact, tmpFact, knownNonnull, prevVnaFrame, targetVnaFrame, IsNullValue.checkedNonNullValue());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                // if (edgeType == IFCMP_EDGE || edgeType ==
                // FALL_THROUGH_EDGE)
                // If this is a fall-through edge from a null check,
                // then we know the value checked is not null.
                if (sourceBlock.isNullCheck() && edgeType == FALL_THROUGH_EDGE) {
                    ValueNumberFrame vnaFrame = vnaDataflow.getStartFact(destBlock);
                    if (vnaFrame == null) {
                        throw new IllegalStateException("no vna frame at block entry?");
                    }
                    Instruction firstInDest = edge.getTarget().getFirstInstruction().getInstruction();
                    IsNullValue instance = fact.getInstance(firstInDest, methodGen.getConstantPool());
                    if (instance.isDefinitelyNull()) {
                        // If we know the variable is null, this edge is
                        // infeasible
                        tmpFact = createFact();
                        tmpFact.setTop();
                    } else if (!instance.isDefinitelyNotNull()) {
                        // If we're not sure that the instance is definitely
                        // non-null,
                        // update the is-null information for the dereferenced
                        // value.
                        InstructionHandle kaBoomLocation = targetBlock.getFirstInstruction();
                        ValueNumber replaceMe = vnaFrame.getInstance(firstInDest, methodGen.getConstantPool());
                        IsNullValue noKaboomNonNullValue = IsNullValue.noKaboomNonNullValue(new Location(kaBoomLocation, targetBlock));
                        if (DEBUG) {
                            System.out.println("Start vna fact: " + vnaFrame);
                            System.out.println("inva fact: " + fact);
                            System.out.println("\nGenerated NoKaboom value for location " + kaBoomLocation);
                            System.out.println("Dereferenced " + instance);
                            System.out.println("On fall through from source block " + sourceBlock);
                        }
                        tmpFact = replaceValues(fact, tmpFact, replaceMe, vnaFrame, targetVnaFrame, noKaboomNonNullValue);
                    }
                }
                // if (sourceBlock.isNullCheck() && edgeType ==
                // FALL_THROUGH_EDGE)
                if (propagatePhiNodeInformation && targetVnaFrame.phiNodeForLoads) {
                    if (DEBUG) {
                        System.out.println("Is phi node for loads");
                    }
                    for (ValueNumber v : fact.getKnownValues()) {
                        AvailableLoad loadForV = sourceVnaFrame.getLoad(v);
                        if (DEBUG) {
                            System.out.println("  " + v + " for " + loadForV);
                        }
                        if (loadForV != null) {
                            ValueNumber[] matchingValueNumbers = targetVnaFrame.getAvailableLoad(loadForV);
                            if (matchingValueNumbers != null) {
                                for (ValueNumber v2 : matchingValueNumbers) {
                                    tmpFact = modifyFrame(fact, tmpFact);
                                    tmpFact.useNewValueNumberForLoad(v, v2);
                                    if (DEBUG) {
                                        System.out.println("For " + loadForV + " switch from " + v + " to " + v2);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (tmpFact != null) {
                fact = tmpFact;
            }
        }
        // if (fact.isValid())
        if (DEBUG) {
            System.out.println("At " + edge);
            System.out.println("Merge " + fact + " into " + result);
        }
        // Normal dataflow merge
        mergeInto(fact, result);
        if (DEBUG) {
            System.out.println("getting " + result);
        }
    }

    @Override
    protected void mergeInto(IsNullValueFrame other, IsNullValueFrame result) throws DataflowreplacedysisException {
        if (other.isTop()) {
            return;
        }
        if (result.isTop()) {
            result.copyFrom(other);
            return;
        }
        super.mergeInto(other, result);
        // FIXME: update decision?
        if (trackValueNumbers) {
            result.mergeKnownValuesWith(other);
        }
    }

    @Override
    public void starreplacederation() {
        // At the beginning of each iteration, clear the set of locations
        // where values become null. That way, after the final iteration
        // of dataflow replacedysis the set should be as accurate as possible.
        locationWhereValueBecomesNullSet.clear();
    }

    public void addLocationWhereValueBecomesNull(LocationWhereValueBecomesNull locationWhereValueBecomesNull) {
        // System.out.println("Location becomes null: " +
        // locationWhereValueBecomesNull );
        locationWhereValueBecomesNullSet.add(locationWhereValueBecomesNull);
    }

    public Set<LocationWhereValueBecomesNull> getLocationWhereValueBecomesNullSet() {
        return locationWhereValueBecomesNullSet;
    }

    @Override
    protected void mergeValues(IsNullValueFrame otherFrame, IsNullValueFrame resultFrame, int slot) throws DataflowreplacedysisException {
        IsNullValue value = IsNullValue.merge(resultFrame.getValue(slot), otherFrame.getValue(slot));
        resultFrame.setValue(slot, value);
    }

    /**
     * Determine if the given basic block ends in a redundant null comparison.
     *
     * @param basicBlock
     *            the basic block
     * @param lastFrame
     *            the IsNullValueFrame representing values at the final
     *            instruction of the block
     * @return an IsNullConditionDecision object representing the is-null
     *         information gained about the compared value, or null if no
     *         information is gained
     */
    private IsNullConditionDecision getDecision(BasicBlock basicBlock, IsNullValueFrame lastFrame) throws DataflowreplacedysisException {
        replacedert lastFrame != null;
        final InstructionHandle lastInSourceHandle = basicBlock.getLastInstruction();
        if (lastInSourceHandle == null) {
            // doesn't end in null comparison
            return null;
        }
        final short lastInSourceOpcode = lastInSourceHandle.getInstruction().getOpcode();
        if (lastInSourceOpcode == Const.IFEQ || lastInSourceOpcode == Const.IFNE) {
            // check for instanceof check
            InstructionHandle prev = lastInSourceHandle.getPrev();
            if (prev == null) {
                return null;
            }
            short secondToLastOpcode = prev.getInstruction().getOpcode();
            // System.out.println("Second last opcode: " +
            // Const.Const.getOpcodeName(secondToLastOpcode));
            if (secondToLastOpcode != Const.INSTANCEOF) {
                return null;
            }
            if (instanceOfFrame == null) {
                return null;
            }
            IsNullValue tos = instanceOfFrame.getTopValue();
            boolean isNotInstanceOf = (lastInSourceOpcode != Const.IFNE);
            Location atInstanceOf = new Location(prev, basicBlock);
            ValueNumberFrame instanceOfVnaFrame = vnaDataflow.getFactAtLocation(atInstanceOf);
            // Initially, replacedume neither branch is feasible.
            IsNullValue ifcmpDecision = null;
            IsNullValue fallThroughDecision = null;
            if (tos.isDefinitelyNull()) {
                // Predetermined comparison - one branch is infeasible
                if (isNotInstanceOf) {
                    ifcmpDecision = tos;
                } else {
                    // ifnonnull
                    fallThroughDecision = tos;
                }
            } else if (tos.isDefinitelyNotNull()) {
                return null;
            } else {
                // As far as we know, both branches feasible
                ifcmpDecision = isNotInstanceOf ? tos : IsNullValue.pathSensitiveNonNullValue();
                fallThroughDecision = isNotInstanceOf ? IsNullValue.pathSensitiveNonNullValue() : tos;
            }
            if (DEBUG) {
                System.out.println("Checking..." + tos + " -> " + ifcmpDecision + " or " + fallThroughDecision);
            }
            return new IsNullConditionDecision(instanceOfVnaFrame.getTopValue(), ifcmpDecision, fallThroughDecision);
        }
        if (!nullComparisonInstructionSet.get(lastInSourceOpcode)) {
            // doesn't end in null comparison
            return null;
        }
        Location atIf = new Location(lastInSourceHandle, basicBlock);
        ValueNumberFrame prevVnaFrame = vnaDataflow.getFactAtLocation(atIf);
        switch(lastInSourceOpcode) {
            case Const.IFNULL:
            case Const.IFNONNULL:
                {
                    IsNullValue tos = lastFrame.getTopValue();
                    boolean ifnull = (lastInSourceOpcode == Const.IFNULL);
                    ValueNumber prevTopValue = prevVnaFrame.getTopValue();
                    return handleIfNull(tos, prevTopValue, ifnull);
                }
            case Const.IF_ACMPEQ:
            case Const.IF_ACMPNE:
                {
                    IsNullValue tos = lastFrame.getStackValue(0);
                    IsNullValue nextToTos = lastFrame.getStackValue(1);
                    boolean tosNull = tos.isDefinitelyNull();
                    boolean nextToTosNull = nextToTos.isDefinitelyNull();
                    boolean cmpeq = (lastInSourceOpcode == Const.IF_ACMPEQ);
                    // Initially, replacedume neither branch is feasible.
                    IsNullValue ifcmpDecision = null;
                    IsNullValue fallThroughDecision = null;
                    ValueNumber value;
                    if (tosNull && nextToTosNull) {
                        // Redundant comparison: both values are null, only one branch
                        // is feasible
                        // no value will be replaced - just want to
                        value = null;
                        // indicate that one of the branches is infeasible
                        if (cmpeq) {
                            ifcmpDecision = IsNullValue.pathSensitiveNullValue();
                        } else {
                            // cmpne
                            fallThroughDecision = IsNullValue.pathSensitiveNullValue();
                        }
                    } else if (tosNull || nextToTosNull) {
                        if (tosNull) {
                            return handleIfNull(nextToTos, prevVnaFrame.getStackValue(1), cmpeq);
                        }
                        replacedert nextToTosNull;
                        return handleIfNull(tos, prevVnaFrame.getStackValue(0), cmpeq);
                    } else if (tos.isDefinitelyNotNull() && !nextToTos.isDefinitelyNotNull()) {
                        // learn that nextToTos is definitely non null on one branch
                        value = prevVnaFrame.getStackValue(1);
                        if (cmpeq) {
                            ifcmpDecision = tos;
                            fallThroughDecision = nextToTos;
                        } else {
                            fallThroughDecision = tos;
                            ifcmpDecision = nextToTos;
                        }
                    } else if (!tos.isDefinitelyNotNull() && nextToTos.isDefinitelyNotNull()) {
                        // learn that tos is definitely non null on one branch
                        value = prevVnaFrame.getStackValue(0);
                        if (cmpeq) {
                            ifcmpDecision = nextToTos;
                            fallThroughDecision = tos;
                        } else {
                            fallThroughDecision = nextToTos;
                            ifcmpDecision = tos;
                        }
                    } else {
                        // No information gained
                        return null;
                    }
                    return new IsNullConditionDecision(value, ifcmpDecision, fallThroughDecision);
                }
            default:
                throw new IllegalStateException();
        }
    }

    private IsNullConditionDecision handleIfNull(IsNullValue tos, ValueNumber prevTopValue, boolean ifnull) {
        // Initially, replacedume neither branch is feasible.
        IsNullValue ifcmpDecision = null;
        IsNullValue fallThroughDecision = null;
        if (tos.isDefinitelyNull()) {
            // Predetermined comparison - one branch is infeasible
            if (ifnull) {
                ifcmpDecision = IsNullValue.pathSensitiveNullValue();
            } else {
                // ifnonnull
                fallThroughDecision = IsNullValue.pathSensitiveNullValue();
            }
        } else if (tos.isDefinitelyNotNull()) {
            // Predetermined comparison - one branch is infeasible
            if (ifnull) {
                fallThroughDecision = tos.wouldHaveBeenAKaboom() ? tos : IsNullValue.pathSensitiveNonNullValue();
            } else {
                // ifnonnull
                ifcmpDecision = tos.wouldHaveBeenAKaboom() ? tos : IsNullValue.pathSensitiveNonNullValue();
            }
        } else {
            // As far as we know, both branches feasible
            ifcmpDecision = ifnull ? IsNullValue.pathSensitiveNullValue() : IsNullValue.pathSensitiveNonNullValue();
            fallThroughDecision = ifnull ? IsNullValue.pathSensitiveNonNullValue() : IsNullValue.pathSensitiveNullValue();
        }
        return new IsNullConditionDecision(prevTopValue, ifcmpDecision, fallThroughDecision);
    }

    /**
     * Update is-null information at a branch target based on information gained
     * at a null comparison branch.
     *
     * @param origFrame
     *            the original is-null frame at entry to basic block
     * @param frame
     *            the modified version of the is-null entry frame; null if the
     *            entry frame has not been modified yet
     * @param replaceMe
     *            the ValueNumber in the value number frame at the if comparison
     *            whose is-null information will be updated
     * @param prevVnaFrame
     *            the ValueNumberFrame at the if comparison
     * @param targetVnaFrame
     *            the ValueNumberFrame at entry to the basic block
     * @param replacementValue
     *            the IsNullValue representing the updated is-null information
     * @return a modified IsNullValueFrame with updated is-null information
     */
    private IsNullValueFrame replaceValues(IsNullValueFrame origFrame, IsNullValueFrame frame, ValueNumber replaceMe, ValueNumberFrame prevVnaFrame, ValueNumberFrame targetVnaFrame, IsNullValue replacementValue) {
        if (!targetVnaFrame.isValid()) {
            throw new IllegalArgumentException("Invalid frame in " + methodGen.getClreplacedName() + "." + methodGen.getName() + " : " + methodGen.getSignature());
        }
        // If required, make a copy of the frame
        frame = modifyFrame(origFrame, frame);
        replacedert frame.getNumSlots() == targetVnaFrame.getNumSlots() : " frame has " + frame.getNumSlots() + ", target has " + targetVnaFrame.getNumSlots() + " in  " + clreplacedAndMethod;
        // The VNA frame may have more slots than the IsNullValueFrame
        // if it was produced by an IF comparison (whose operand or operands
        // are subsequently popped off the stack).
        final int targetNumSlots = targetVnaFrame.getNumSlots();
        final int prefixNumSlots = Math.min(frame.getNumSlots(), prevVnaFrame.getNumSlots());
        if (trackValueNumbers) {
            AvailableLoad loadForV = prevVnaFrame.getLoad(replaceMe);
            if (DEBUG && loadForV != null) {
                System.out.println("For " + replaceMe + " availableLoad is " + loadForV);
                ValueNumber[] matchingValueNumbers = targetVnaFrame.getAvailableLoad(loadForV);
                if (matchingValueNumbers != null) {
                    for (ValueNumber v2 : matchingValueNumbers) {
                        System.out.println("  matches " + v2);
                    }
                }
            }
            if (loadForV != null) {
                ValueNumber[] matchingValueNumbers = targetVnaFrame.getAvailableLoad(loadForV);
                if (matchingValueNumbers != null) {
                    for (ValueNumber v2 : matchingValueNumbers) {
                        if (!replaceMe.equals(v2)) {
                            frame.setKnownValue(v2, replacementValue);
                            if (DEBUG) {
                                System.out.println("For " + loadForV + " switch from " + replaceMe + " to " + v2);
                            }
                        }
                    }
                }
            }
            frame.setKnownValue(replaceMe, replacementValue);
        }
        // Here's the deal:
        // - "replaceMe" is the value number from the previous frame (at the if
        // branch)
        // which indicates a value that we have updated is-null information
        // about
        // - in the target value number frame (at entry to the target block),
        // we find the value number in the stack slot corresponding to the
        // "replaceMe"
        // value; this is the "corresponding" value
        // - all instances of the "corresponding" value in the target frame have
        // their is-null information updated to "replacementValue"
        // This should thoroughly make use of the updated information.
        for (int i = 0; i < prefixNumSlots; ++i) {
            if (prevVnaFrame.getValue(i).equals(replaceMe)) {
                ValueNumber corresponding = targetVnaFrame.getValue(i);
                for (int j = 0; j < targetNumSlots; ++j) {
                    if (targetVnaFrame.getValue(j).equals(corresponding)) {
                        frame.setValue(j, replacementValue);
                    }
                }
            }
        }
        return frame;
    }

    public IsNullValueFrame getFactAtMidEdge(Edge edge) throws DataflowreplacedysisException {
        BasicBlock block = isForwards() ? edge.getSource() : edge.getTarget();
        IsNullValueFrame predFact = createFact();
        copy(getResultFact(block), predFact);
        edgeTransfer(edge, predFact);
        IsNullValueFrame result = createFact();
        makeFactTop(result);
        meetInto(predFact, edge, result, false);
        return result;
    }
}

18 Source : ClassContext.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Look up the Method represented by given MethodGen.
 *
 * @param methodGen
 *            a MethodGen
 * @return the Method represented by the MethodGen
 */
public Method getMethod(MethodGen methodGen) {
    Method[] methodList = jclreplaced.getMethods();
    for (Method method : methodList) {
        if (method.getName().equals(methodGen.getName()) && method.getSignature().equals(methodGen.getSignature()) && method.getAccessFlags() == methodGen.getAccessFlags()) {
            return method;
        }
    }
    return null;
}

18 Source : TaintFrame.java
with GNU Lesser General Public License v3.0
from blackarbiter

public String toString(MethodGen method) {
    String[] variables = new String[method.getLocalVariables().length];
    LocalVariableGen[] variablesGen = method.getLocalVariables();
    for (int i = 0; i < variablesGen.length; i++) {
        variables[i] = variablesGen[i].getName();
    }
    return toString(variables);
}

18 Source : AbstractTaintDetector.java
with GNU Lesser General Public License v3.0
from blackarbiter

private static String getFullMethodName(MethodGen methodGen) {
    String methodNameWithSignature = methodGen.getName() + methodGen.getSignature();
    String slashedClreplacedName = methodGen.getClreplacedName().replace('.', '/');
    return slashedClreplacedName + "." + methodNameWithSignature;
}

17 Source : NoiseNullDeref.java
with GNU Lesser General Public License v2.1
from spotbugs

private void replacedyzeMethod(ClreplacedContext clreplacedContext, Method method) throws DataflowreplacedysisException, CFGBuilderException {
    if (DEBUG || DEBUG_NULLARG) {
        System.out.println("Pre FND ");
    }
    MethodGen methodGen = clreplacedContext.getMethodGen(method);
    if (methodGen == null) {
        return;
    }
    // UsagesRequiringNonNullValues uses =
    // clreplacedContext.getUsagesRequiringNonNullValues(method);
    this.method = method;
    if (DEBUG || DEBUG_NULLARG) {
        System.out.println("FND: " + SignatureConverter.convertMethodSignature(methodGen));
    }
    findPreviouslyDeadBlocks();
    vnaDataflow = clreplacedContext.getValueNumberDataflow(method);
    // Create a NullDerefAndRedundantComparisonFinder object to do the
    // actual
    // work. It will call back to report null derefs and redundant null
    // comparisons
    // through the NullDerefAndRedundantComparisonCollector interface we
    // implement.
    NullDerefAndRedundantComparisonFinder worker = new NullDerefAndRedundantComparisonFinder(clreplacedContext, method, this);
    worker.execute();
}

17 Source : FindInconsistentSync2.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Determine whether or not the the given method is a getter method. I.e.,
 * if it just returns the value of an instance field.
 *
 * @param clreplacedContext
 *            the ClreplacedContext for the clreplaced containing the method
 * @param method
 *            the method
 */
public static boolean isGetterMethod(ClreplacedContext clreplacedContext, Method method) {
    MethodGen methodGen = clreplacedContext.getMethodGen(method);
    if (methodGen == null) {
        return false;
    }
    InstructionList il = methodGen.getInstructionList();
    // System.out.println("Checking getter method: " + method.getName());
    if (il.getLength() > 60) {
        return false;
    }
    int count = 0;
    for (InstructionHandle ih : il) {
        switch(ih.getInstruction().getOpcode()) {
            case Const.GETFIELD:
                count++;
                if (count > 1) {
                    return false;
                }
                break;
            case Const.PUTFIELD:
            case Const.BALOAD:
            case Const.CALOAD:
            case Const.DALOAD:
            case Const.FALOAD:
            case Const.IALOAD:
            case Const.LALOAD:
            case Const.SALOAD:
            case Const.AALOAD:
            case Const.BASTORE:
            case Const.CASTORE:
            case Const.DASTORE:
            case Const.FASTORE:
            case Const.IASTORE:
            case Const.LASTORE:
            case Const.SASTORE:
            case Const.AASTORE:
            case Const.PUTSTATIC:
                return false;
            case Const.INVOKESTATIC:
            case Const.INVOKEVIRTUAL:
            case Const.INVOKEINTERFACE:
            case Const.INVOKESPECIAL:
            case Const.GETSTATIC:
        }
    }
    // System.out.println("Found getter method: " + method.getName());
    return true;
}

17 Source : DontIgnoreResultOfPutIfAbsent.java
with GNU Lesser General Public License v2.1
from spotbugs

@Override
public void visitClreplacedContext(ClreplacedContext clreplacedContext) {
    JavaClreplaced javaClreplaced = clreplacedContext.getJavaClreplaced();
    ConstantPool pool = javaClreplaced.getConstantPool();
    boolean found = false;
    for (Constant constantEntry : pool.getConstantPool()) {
        if (constantEntry instanceof ConstantNameAndType) {
            ConstantNameAndType nt = (ConstantNameAndType) constantEntry;
            if ("putIfAbsent".equals(nt.getName(pool))) {
                found = true;
                break;
            }
        }
    }
    if (!found) {
        return;
    }
    Method[] methodList = javaClreplaced.getMethods();
    for (Method method : methodList) {
        MethodGen methodGen = clreplacedContext.getMethodGen(method);
        if (methodGen == null) {
            continue;
        }
        try {
            replacedyzeMethod(clreplacedContext, method);
        } catch (DataflowreplacedysisException e) {
            bugReporter.logError("Error replacedyzing " + method.toString(), e);
        } catch (CFGBuilderException e) {
            bugReporter.logError("Error replacedyzing " + method.toString(), e);
        }
    }
}

17 Source : UnconditionalValueDerefDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public UnconditionalValueDerefDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        throw new MethodUnprofitableException(descriptor);
    }
    CFG cfg = getCFG(replacedysisCache, descriptor);
    ValueNumberDataflow vnd = getValueNumberDataflow(replacedysisCache, descriptor);
    UnconditionalValueDerefreplacedysis replacedysis = new UnconditionalValueDerefreplacedysis(getReverseDepthFirstSearch(replacedysisCache, descriptor), getDepthFirstSearch(replacedysisCache, descriptor), cfg, getMethod(replacedysisCache, descriptor), methodGen, vnd, getreplacedertionMethods(replacedysisCache, descriptor.getClreplacedDescriptor()));
    IsNullValueDataflow inv = getIsNullValueDataflow(replacedysisCache, descriptor);
    // XXX: hack to clear derefs on not-null branches
    replacedysis.clearDerefsOnNonNullBranches(inv);
    TypeDataflow typeDataflow = getTypeDataflow(replacedysisCache, descriptor);
    // XXX: type replacedysis is needed to resolve method calls for
    // checking whether call targets unconditionally dereference parameters
    replacedysis.setTypeDataflow(typeDataflow);
    UnconditionalValueDerefDataflow dataflow = new UnconditionalValueDerefDataflow(cfg, replacedysis);
    dataflow.execute();
    if (ClreplacedContext.DUMP_DATAFLOW_replacedYSIS) {
        dataflow.dumpDataflow(replacedysis);
    }
    if (UnconditionalValueDerefreplacedysis.DEBUG) {
        ClreplacedContext.dumpDataflowInformation(getMethod(replacedysisCache, descriptor), cfg, vnd, inv, dataflow, typeDataflow);
    }
    return dataflow;
}

17 Source : TypeDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public TypeDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        throw new MethodUnprofitableException(descriptor);
    }
    CFG cfg = getCFG(replacedysisCache, descriptor);
    DepthFirstSearch dfs = getDepthFirstSearch(replacedysisCache, descriptor);
    ExceptionSetFactory exceptionSetFactory = getExceptionSetFactory(replacedysisCache, descriptor);
    Method method = getMethod(replacedysisCache, descriptor);
    Typereplacedysis typereplacedysis = new Typereplacedysis(method, methodGen, cfg, dfs, replacedysisContext.currentreplacedysisContext().getLookupFailureCallback(), exceptionSetFactory);
    if (replacedysisContext.currentreplacedysisContext().getBoolProperty(replacedysisFeatures.MODEL_INSTANCEOF)) {
        typereplacedysis.setValueNumberDataflow(getValueNumberDataflow(replacedysisCache, descriptor));
    }
    // Field store type database.
    // If present, this can give us more accurate type information
    // for values loaded from fields.
    typereplacedysis.setFieldStoreTypeDatabase(replacedysisContext.currentreplacedysisContext().getFieldStoreTypeDatabase());
    TypeDataflow typeDataflow = new TypeDataflow(cfg, typereplacedysis);
    try {
        typeDataflow.execute();
    } catch (CheckedreplacedysisException e) {
        replacedysisContext.logError("Error performing type dataflow replacedysis of " + descriptor, e);
        throw e;
    }
    if (Typereplacedysis.DEBUG || ClreplacedContext.DUMP_DATAFLOW_replacedYSIS) {
        ClreplacedContext.dumpTypeDataflow(method, cfg, typeDataflow);
    }
    return typeDataflow;
}

17 Source : LockDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public LockDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        throw new MethodUnprofitableException(descriptor);
    }
    ValueNumberDataflow vnaDataflow = getValueNumberDataflow(replacedysisCache, descriptor);
    DepthFirstSearch dfs = getDepthFirstSearch(replacedysisCache, descriptor);
    CFG cfg = getCFG(replacedysisCache, descriptor);
    Lockreplacedysis replacedysis = new Lockreplacedysis(methodGen, vnaDataflow, dfs);
    LockDataflow dataflow = new LockDataflow(cfg, replacedysis);
    dataflow.execute();
    return dataflow;
}

17 Source : CFGDetector.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.Detector2#visitClreplaced(edu.umd.cs.findbugs.clreplacedfile
     * .ClreplacedDescriptor)
     */
@Override
public void visitClreplaced(ClreplacedDescriptor clreplacedDescriptor) throws CheckedreplacedysisException {
    IreplacedysisCache replacedysisCache = Global.getreplacedysisCache();
    JavaClreplaced jclreplaced = replacedysisCache.getClreplacedreplacedysis(JavaClreplaced.clreplaced, clreplacedDescriptor);
    clreplacedContext = replacedysisCache.getClreplacedreplacedysis(ClreplacedContext.clreplaced, clreplacedDescriptor);
    for (Method m : clreplacedContext.getMethodsInCallOrder()) {
        if (m.getCode() == null) {
            continue;
        }
        method = m;
        MethodDescriptor methodDescriptor = BCELUtil.getMethodDescriptor(jclreplaced, method);
        // Try to get MethodGen. If we can't get one,
        // then this method should be skipped.
        MethodGen methodGen = replacedysisCache.getMethodreplacedysis(MethodGen.clreplaced, methodDescriptor);
        if (methodGen == null) {
            continue;
        }
        CFG cfg = replacedysisCache.getMethodreplacedysis(CFG.clreplaced, methodDescriptor);
        visitMethodCFG(methodDescriptor, cfg);
    }
}

17 Source : UnconditionalValueDerefAnalysis.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Dataflow replacedysis to find values unconditionally dereferenced in the future.
 *
 * @author David Hovemeyer
 */
public clreplaced UnconditionalValueDerefreplacedysis extends BackwardDataflowreplacedysis<UnconditionalValueDerefSet> {

    public static final boolean DEBUG = SystemProperties.getBoolean("fnd.derefs.debug");

    public static final boolean replacedUME_NONZERO_TRIP_LOOPS = SystemProperties.getBoolean("fnd.derefs.nonzerotrip");

    public static final boolean IGNORE_DEREF_OF_NCP = SystemProperties.getBoolean("fnd.derefs.ignoreNCP", false);

    public static final boolean CHECK_ANNOTATIONS = SystemProperties.getBoolean("fnd.derefs.checkannotations", true);

    public static final boolean CHECK_CALLS = SystemProperties.getBoolean("fnd.derefs.checkcalls", true);

    public static final boolean DEBUG_CHECK_CALLS = SystemProperties.getBoolean("fnd.derefs.checkcalls.debug");

    private static final int[] NULLCHECK1 = { Opcodes.DUP, Opcodes.INVOKESPECIAL, Opcodes.ATHROW };

    private static final int[] NULLCHECK2 = { Opcodes.DUP, Opcodes.LDC, Opcodes.INVOKESPECIAL, Opcodes.ATHROW };

    private final CFG cfg;

    private final Method method;

    private final MethodGen methodGen;

    private final ValueNumberDataflow vnaDataflow;

    private final replacedertionMethods replacedertionMethods;

    private IsNullValueDataflow invDataflow;

    private TypeDataflow typeDataflow;

    /**
     * Constructor.
     *
     * @param rdfs
     *            the reverse depth-first-search (for the block order)
     * @param cfg
     *            the CFG for the method
     * @param methodGen
     *            the MethodGen for the method
     * @param vnaDataflow
     * @param replacedertionMethods
     *            replacedertionMethods for the replacedyzed clreplaced
     */
    public UnconditionalValueDerefreplacedysis(ReverseDepthFirstSearch rdfs, DepthFirstSearch dfs, CFG cfg, Method method, MethodGen methodGen, ValueNumberDataflow vnaDataflow, replacedertionMethods replacedertionMethods) {
        super(rdfs, dfs);
        this.cfg = cfg;
        this.methodGen = methodGen;
        this.method = method;
        this.vnaDataflow = vnaDataflow;
        this.replacedertionMethods = replacedertionMethods;
        if (DEBUG) {
            System.out.println("UnconditionalValueDerefreplacedysis replacedysis " + methodGen.getClreplacedName() + "." + methodGen.getName() + " : " + methodGen.getSignature());
        }
    }

    @Override
    public String toString() {
        return this.getClreplaced().getSimpleName() + " of " + method;
    }

    /**
     * HACK: use the given is-null dataflow to clear deref sets for values that
     * are known to be definitely non-null on a branch.
     *
     * @param invDataflow
     *            the IsNullValueDataflow to use
     */
    public void clearDerefsOnNonNullBranches(IsNullValueDataflow invDataflow) {
        this.invDataflow = invDataflow;
    }

    public void setTypeDataflow(TypeDataflow typeDataflow) {
        this.typeDataflow = typeDataflow;
    }

    @Override
    public boolean isFactValid(UnconditionalValueDerefSet fact) {
        return !fact.isTop() && !fact.isBottom();
    }

    private static boolean check(InstructionHandle h, int[] opcodes) {
        for (int opcode : opcodes) {
            if (h == null) {
                return false;
            }
            short opcode2 = h.getInstruction().getOpcode();
            if (opcode == Const.LDC) {
                switch(opcode2) {
                    case Const.LDC:
                    case Const.ALOAD:
                    case Const.ALOAD_0:
                    case Const.ALOAD_1:
                    case Const.ALOAD_2:
                    case Const.ALOAD_3:
                        break;
                    default:
                        return false;
                }
            } else if (opcode2 != opcode) {
                return false;
            }
            h = h.getNext();
        }
        return true;
    }

    public static boolean isNullCheck(InstructionHandle h, ConstantPoolGen cpg) {
        if (!(h.getInstruction() instanceof IFNONNULL)) {
            return false;
        }
        h = h.getNext();
        final Instruction newInstruction = h.getInstruction();
        if (!(newInstruction instanceof NEW)) {
            return false;
        }
        final ObjectType loadClreplacedType = ((NEW) newInstruction).getLoadClreplacedType(cpg);
        if (!"java.lang.NullPointerException".equals(loadClreplacedType.getClreplacedName())) {
            return false;
        }
        h = h.getNext();
        return check(h, NULLCHECK1) || check(h, NULLCHECK2);
    }

    private void handleNullCheck(Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        if (reportPotentialDereference(location, invDataflow.getFactAtLocation(location))) {
            ValueNumber vn = vnaFrame.getTopValue();
            fact.addDeref(vn, location);
        }
    }

    public static boolean reportPotentialDereference(Location location, IsNullValueFrame invFrame) throws DataflowreplacedysisException {
        if (!invFrame.isValid()) {
            return false;
        }
        IsNullValue value = invFrame.getTopValue();
        return !(value.isDefinitelyNotNull() || value.isDefinitelyNull());
    }

    @Override
    public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        Instruction instruction = handle.getInstruction();
        if (fact.isTop()) {
            return;
        }
        Location location = new Location(handle, basicBlock);
        // If this is a call to an replacedertion method,
        // change the dataflow value to be TOP.
        // We don't want to report future derefs that would
        // be guaranteed only if the replacedertion methods
        // returns normally.
        // TODO: at some point, evaluate whether we should revisit this
        if (// || handle.getInstruction() instanceof ATHROW
        isreplacedertion(handle)) {
            if (DEBUG) {
                System.out.println("MAKING BOTTOM0 AT: " + location);
            }
            fact.clear();
            return;
        }
        // Get value number frame
        ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(location);
        if (!vnaFrame.isValid()) {
            if (DEBUG) {
                System.out.println("MAKING TOP1 AT: " + location);
            }
            // Probably dead code.
            // replacedume this location can't be reached.
            makeFactTop(fact);
            return;
        }
        if (isNullCheck(handle, methodGen.getConstantPool())) {
            handleNullCheck(location, vnaFrame, fact);
        }
        // Check for calls to a method that unconditionally dereferences
        // a parameter. Mark any such arguments as derefs.
        if (CHECK_CALLS && instruction instanceof InvokeInstruction) {
            checkUnconditionalDerefDatabase(location, vnaFrame, fact);
        }
        // If this is a method call instruction,
        // check to see if any of the parameters are @NonNull,
        // and treat them as dereferences.
        if (CHECK_ANNOTATIONS && instruction instanceof InvokeInstruction) {
            checkNonNullParams(location, vnaFrame, fact);
        }
        if (CHECK_ANNOTATIONS && instruction instanceof ARETURN) {
            XMethod thisMethod = XFactory.createXMethod(methodGen);
            checkNonNullReturnValue(thisMethod, location, vnaFrame, fact);
        }
        if (CHECK_ANNOTATIONS && (instruction instanceof PUTFIELD || instruction instanceof PUTSTATIC)) {
            checkNonNullPutField(location, vnaFrame, fact);
        }
        // Check to see if an instance value is dereferenced here
        checkInstance(location, vnaFrame, fact);
        /*
        if (false) {
            fact.cleanDerefSet(location, vnaFrame);
        }*/
        if (DEBUG && fact.isTop()) {
            System.out.println("MAKING TOP2 At: " + location);
        }
    }

    /**
     * Check method call at given location to see if it unconditionally
     * dereferences a parameter. Mark any such arguments as derefs.
     *
     * @param location
     *            the Location of the method call
     * @param vnaFrame
     *            ValueNumberFrame at the Location
     * @param fact
     *            the dataflow value to modify
     * @throws DataflowreplacedysisException
     */
    private void checkUnconditionalDerefDatabase(Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        ConstantPoolGen constantPool = methodGen.getConstantPool();
        for (ValueNumber vn : checkUnconditionalDerefDatabase(location, vnaFrame, constantPool, invDataflow.getFactAtLocation(location), typeDataflow)) {
            fact.addDeref(vn, location);
        }
    }

    public static Set<ValueNumber> checkUnconditionalDerefDatabase(Location location, ValueNumberFrame vnaFrame, ConstantPoolGen constantPool, @CheckForNull IsNullValueFrame invFrame, TypeDataflow typeDataflow) throws DataflowreplacedysisException {
        if (invFrame != null && !invFrame.isValid()) {
            return Collections.emptySet();
        }
        InvokeInstruction inv = (InvokeInstruction) location.getHandle().getInstruction();
        SignatureParser sigParser = new SignatureParser(inv.getSignature(constantPool));
        int numParams = sigParser.getNumParameters();
        if (numParams == 0 || !sigParser.hasReferenceParameters()) {
            return Collections.emptySet();
        }
        ParameterNullnessPropertyDatabase database = replacedysisContext.currentreplacedysisContext().getUnconditionalDerefParamDatabase();
        if (database == null) {
            if (DEBUG_CHECK_CALLS) {
                System.out.println("no database!");
            }
            return Collections.emptySet();
        }
        TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);
        if (!typeFrame.isValid()) {
            if (DEBUG_CHECK_CALLS) {
                System.out.println("invalid type frame!");
            }
            return Collections.emptySet();
        }
        try {
            Set<XMethod> targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, constantPool);
            if (targetSet.isEmpty()) {
                return Collections.emptySet();
            }
            if (DEBUG_CHECK_CALLS) {
                System.out.println("target set size: " + targetSet.size());
            }
            // Compute the intersection of all properties
            ParameterProperty derefParamSet = null;
            for (XMethod target : targetSet) {
                if (target.isStub()) {
                    continue;
                }
                if (DEBUG_CHECK_CALLS) {
                    System.out.print("Checking: " + target + ": ");
                }
                ParameterProperty targetDerefParamSet = database.getProperty(target.getMethodDescriptor());
                if (targetDerefParamSet == null) {
                    // Hmm...no information for this target.
                    // replacedume it doesn't dereference anything
                    if (DEBUG_CHECK_CALLS) {
                        System.out.println("==> no information, replacedume no guaranteed dereferences");
                    }
                    return Collections.emptySet();
                }
                if (DEBUG_CHECK_CALLS) {
                    System.out.println("==> " + targetDerefParamSet);
                }
                if (derefParamSet == null) {
                    derefParamSet = new ParameterProperty();
                    derefParamSet.copyFrom(targetDerefParamSet);
                } else {
                    derefParamSet.intersectWith(targetDerefParamSet);
                }
            }
            if (derefParamSet == null || derefParamSet.isEmpty()) {
                if (DEBUG) {
                    System.out.println("** Nothing");
                }
                return Collections.emptySet();
            }
            if (DEBUG_CHECK_CALLS) {
                System.out.println("** Summary of call @ " + location.getHandle().getPosition() + ": " + derefParamSet);
            }
            HashSet<ValueNumber> requiredToBeNonnull = new HashSet<>();
            for (int i = 0; i < numParams; i++) {
                if (!derefParamSet.hasProperty(i)) {
                    continue;
                }
                int argSlot = vnaFrame.getStackLocation(sigParser.getSlotsFromTopOfStackForParameter(i));
                if (invFrame != null && !reportDereference(invFrame, argSlot)) {
                    continue;
                }
                if (DEBUG_CHECK_CALLS) {
                    System.out.println("  dereference @ " + location.getHandle().getPosition() + " of parameter " + i);
                }
                requiredToBeNonnull.add(vnaFrame.getValue(argSlot));
            }
            return requiredToBeNonnull;
        } catch (ClreplacedNotFoundException e) {
            replacedysisContext.reportMissingClreplaced(e);
        }
        return Collections.emptySet();
    }

    public static final boolean VERBOSE_NULLARG_DEBUG = SystemProperties.getBoolean("fnd.debug.nullarg.verbose");

    /**
     * If this is a method call instruction, check to see if any of the
     * parameters are @NonNull, and treat them as dereferences.
     *
     * @param location
     *            the Location of the instruction
     * @param vnaFrame
     *            the ValueNumberFrame at the Location of the instruction
     * @param fact
     *            the dataflow value to modify
     *
     * @throws DataflowreplacedysisException
     */
    private void checkNonNullReturnValue(XMethod thisMethod, Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        INullnessAnnotationDatabase database = replacedysisContext.currentreplacedysisContext().getNullnessAnnotationDatabase();
        if (database.getResolvedAnnotation(thisMethod, true) != NullnessAnnotation.NONNULL) {
            return;
        }
        if (reportPotentialDereference(location, invDataflow.getFactAtLocation(location))) {
            ValueNumber vn = vnaFrame.getTopValue();
            fact.addDeref(vn, location);
        }
    }

    /**
     * If this is a putfield or putstatic instruction, check to see if the field
     * is @NonNull, and treat it as dereferences.
     *
     * @param location
     *            the Location of the instruction
     * @param vnaFrame
     *            the ValueNumberFrame at the Location of the instruction
     * @param fact
     *            the dataflow value to modify
     * @throws DataflowreplacedysisException
     */
    private void checkNonNullPutField(Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        INullnessAnnotationDatabase database = replacedysisContext.currentreplacedysisContext().getNullnessAnnotationDatabase();
        FieldInstruction fieldIns = (FieldInstruction) location.getHandle().getInstruction();
        XField field = XFactory.createXField(fieldIns, methodGen.getConstantPool());
        char firstChar = field.getSignature().charAt(0);
        if (firstChar != 'L' && firstChar != '[') {
            return;
        }
        NullnessAnnotation resolvedAnnotation = database.getResolvedAnnotation(field, true);
        if (resolvedAnnotation == NullnessAnnotation.NONNULL) {
            IsNullValueFrame invFrame = invDataflow.getFactAtLocation(location);
            if (!invFrame.isValid()) {
                return;
            }
            IsNullValue value = invFrame.getTopValue();
            if (reportDereference(value)) {
                ValueNumber vn = vnaFrame.getTopValue();
                fact.addDeref(vn, location);
            }
        }
    }

    /**
     * If this is a method call instruction, check to see if any of the
     * parameters are @NonNull, and treat them as dereferences.
     *
     * @param location
     *            the Location of the instruction
     * @param vnaFrame
     *            the ValueNumberFrame at the Location of the instruction
     * @param fact
     *            the dataflow value to modify
     * @throws DataflowreplacedysisException
     */
    private void checkNonNullParams(Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        ConstantPoolGen constantPool = methodGen.getConstantPool();
        Set<ValueNumber> nonNullParams = checkNonNullParams(location, vnaFrame, constantPool, method, invDataflow.getFactAtLocation(location));
        for (ValueNumber vn : nonNullParams) {
            fact.addDeref(vn, location);
        }
    }

    public static Set<ValueNumber> checkAllNonNullParams(Location location, ValueNumberFrame vnaFrame, ConstantPoolGen constantPool, @CheckForNull Method method, @CheckForNull IsNullValueDataflow invDataflow, TypeDataflow typeDataflow) throws DataflowreplacedysisException {
        IsNullValueFrame invFrame = null;
        if (invDataflow != null) {
            invFrame = invDataflow.getFactAtLocation(location);
        }
        Set<ValueNumber> result1 = checkNonNullParams(location, vnaFrame, constantPool, method, invFrame);
        Set<ValueNumber> result2 = checkUnconditionalDerefDatabase(location, vnaFrame, constantPool, invFrame, typeDataflow);
        if (result1.isEmpty()) {
            return result2;
        }
        if (result2.isEmpty()) {
            return result1;
        }
        result1.addAll(result2);
        return result1;
    }

    public static Set<ValueNumber> checkNonNullParams(Location location, ValueNumberFrame vnaFrame, ConstantPoolGen constantPool, @CheckForNull Method method, @CheckForNull IsNullValueFrame invFrame) throws DataflowreplacedysisException {
        if (invFrame != null && !invFrame.isValid()) {
            return Collections.emptySet();
        }
        INullnessAnnotationDatabase database = replacedysisContext.currentreplacedysisContext().getNullnessAnnotationDatabase();
        InvokeInstruction inv = (InvokeInstruction) location.getHandle().getInstruction();
        if (inv instanceof INVOKEDYNAMIC) {
            // ignore indy, it's only used to create lambda instances
            return Collections.emptySet();
        }
        XMethod called = XFactory.createXMethod(inv, constantPool);
        SignatureParser sigParser = new SignatureParser(called.getSignature());
        int numParams = sigParser.getNumParameters();
        Set<ValueNumber> result = new HashSet<>();
        Iterator<String> parameterIterator = sigParser.parameterSignatureIterator();
        for (int i = 0; i < numParams; i++) {
            String parameterSignature = parameterIterator.next();
            char firstChar = parameterSignature.charAt(0);
            if (firstChar != 'L' && firstChar != '[') {
                continue;
            }
            int offset = sigParser.getSlotsFromTopOfStackForParameter(i);
            if (invFrame != null) {
                int slot = invFrame.getStackLocation(offset);
                if (!reportDereference(invFrame, slot)) {
                    continue;
                }
            }
            if (database.parameterMustBeNonNull(called, i)) {
                int catchSizeNPE = Util.getSizeOfSurroundingTryBlock(method, "java/lang/NullPointerException", location.getHandle().getPosition());
                int catchSizeNFE = Util.getSizeOfSurroundingTryBlock(method, "java/lang/NumberFormatException", location.getHandle().getPosition());
                if (catchSizeNPE == Integer.MAX_VALUE && (!Values.DOTTED_JAVA_LANG_INTEGER.equals(called.getClreplacedName()) || catchSizeNFE == Integer.MAX_VALUE)) {
                    // Get the corresponding value number
                    ValueNumber vn = vnaFrame.getArgument(inv, constantPool, i, sigParser);
                    result.add(vn);
                }
            }
        }
        return result;
    }

    /**
     * Check to see if the instruction has a null check replacedociated with it, and
     * if so, add a dereference.
     *
     * @param location
     *            the Location of the instruction
     * @param vnaFrame
     *            ValueNumberFrame at the Location of the instruction
     * @param fact
     *            the dataflow value to modify
     * @throws DataflowreplacedysisException
     */
    private void checkInstance(Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowreplacedysisException {
        // See if this instruction has a null check.
        // If it does, the fall through predecessor will be
        // identify itself as the null check.
        if (!location.isFirstInstructionInBasicBlock()) {
            return;
        }
        if (invDataflow == null) {
            return;
        }
        BasicBlock fallThroughPredecessor = cfg.getPredecessorWithEdgeType(location.getBasicBlock(), EdgeTypes.FALL_THROUGH_EDGE);
        if (fallThroughPredecessor == null || !fallThroughPredecessor.isNullCheck()) {
            return;
        }
        // Get the null-checked value
        ValueNumber vn = vnaFrame.getInstance(location.getHandle().getInstruction(), methodGen.getConstantPool());
        // Ignore dereferences of this
        if (!methodGen.isStatic()) {
            ValueNumber v = vnaFrame.getValue(0);
            if (v.equals(vn)) {
                return;
            }
        }
        if (vn.hasFlag(ValueNumber.CONSTANT_CLreplaced_OBJECT)) {
            return;
        }
        IsNullValueFrame startFact = null;
        startFact = invDataflow.getStartFact(fallThroughPredecessor);
        if (!startFact.isValid()) {
            return;
        }
        int slot = startFact.getInstanceSlot(location.getHandle().getInstruction(), methodGen.getConstantPool());
        if (!reportDereference(startFact, slot)) {
            return;
        }
        if (DEBUG) {
            System.out.println("FOUND GUARANTEED DEREFERENCE");
            System.out.println("Load: " + vnaFrame.getLoad(vn));
            System.out.println("Pred: " + fallThroughPredecessor);
            System.out.println("startFact: " + startFact);
            System.out.println("Location: " + location);
            System.out.println("Value number frame: " + vnaFrame);
            System.out.println("Dereferenced valueNumber: " + vn);
            System.out.println("invDataflow: " + startFact);
            System.out.println("IGNORE_DEREF_OF_NCP: " + IGNORE_DEREF_OF_NCP);
        }
        // Mark the value number as being dereferenced at this location
        fact.addDeref(vn, location);
    }

    private static boolean reportDereference(IsNullValueFrame invFrameAtNullCheck, int instance) {
        return reportDereference(invFrameAtNullCheck.getValue(instance));
    }

    private static boolean reportDereference(IsNullValue value) {
        return !(value.isDefinitelyNotNull() || value.isDefinitelyNull() || (IGNORE_DEREF_OF_NCP && value.isNullOnComplicatedPath()));
    }

    /**
     * Return whether or not given instruction is an replacedertion.
     *
     * @param handle
     *            the instruction
     * @return true if instruction is an replacedertion, false otherwise
     */
    private boolean isreplacedertion(InstructionHandle handle) {
        return replacedertionMethods.isreplacedertionHandle(handle, methodGen.getConstantPool());
    }

    @Override
    public void copy(UnconditionalValueDerefSet source, UnconditionalValueDerefSet dest) {
        dest.makeSameAs(source);
    }

    @Override
    public UnconditionalValueDerefSet createFact() {
        return new UnconditionalValueDerefSet(vnaDataflow.getreplacedysis().getNumValuesAllocated());
    }

    @Override
    public void initEntryFact(UnconditionalValueDerefSet result) throws DataflowreplacedysisException {
        result.clear();
    }

    // /* (non-Javadoc)
    // * @see
    // edu.umd.cs.findbugs.ba.Dataflowreplacedysis#initResultFact(java.lang.Object)
    // */
    // public void initResultFact(UnconditionalValueDerefSet result) {
    // result.setIsTop();
    // }
    @Override
    public void makeFactTop(UnconditionalValueDerefSet fact) {
        fact.setIsTop();
    }

    @Override
    public boolean isTop(UnconditionalValueDerefSet fact) {
        return fact.isTop();
    }

    @Override
    public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result) throws DataflowreplacedysisException {
        meetInto(fact, edge, result, false);
    }

    public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result, boolean onlyEdge) {
        if (isExceptionEdge(edge) && !onlyEdge) {
            if (DEBUG) {
                System.out.println("Skipping exception edge");
            }
            return;
        }
        ValueNumber knownNonnullOnBranch = null;
        // Edge transfer function
        if (isFactValid(fact)) {
            fact = propagateDerefSetsToMergeInputValues(fact, edge);
            if (invDataflow != null) {
                knownNonnullOnBranch = findValueKnownNonnullOnBranch(fact, edge);
                if (knownNonnullOnBranch != null) {
                    fact = duplicateFact(fact);
                    fact.clearDerefSet(knownNonnullOnBranch);
                }
            }
        }
        boolean isBackEdge = edge.isBackwardInBytecode();
        Set<Integer> loopExitBranches = ClreplacedContext.getLoopExitBranches(method, methodGen);
        replacedert loopExitBranches != null;
        boolean sourceIsTopOfLoop = edge.sourceIsTopOfLoop(loopExitBranches);
        if (sourceIsTopOfLoop && edge.getType() == EdgeTypes.FALL_THROUGH_EDGE) {
            isBackEdge = true;
        }
        /*
        if (false && (edge.getType() == EdgeTypes.IFCMP_EDGE || sourceIsTopOfLoop)) {
            System.out.println("Meet into " + edge);
            System.out.println("  foo2: " + sourceIsTopOfLoop);
            System.out.println("  getType: " + edge.getType());
            System.out.println("  Backedge according to bytecode: " + isBackEdge);
            System.out.println("  Fact hashCode: " + System.idenreplacedyHashCode(result));
            System.out.println("  Initial fact: " + result);
            System.out.println("  Edge fact: " + fact);
        }
         */
        if (result.isTop() || fact.isBottom()) {
            // Make result identical to other fact
            copy(fact, result);
            if (replacedUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop()) {
                result.resultsFromBackEdge = true;
            }
        } else if (replacedUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop()) {
            result.unionWith(fact, vnaDataflow.getreplacedysis().getFactory());
            result.resultsFromBackEdge = true;
            if (DEBUG) {
                System.out.println("\n Forcing union of " + System.idenreplacedyHashCode(result) + " due to backedge info");
                System.out.println("  result: " + result);
            }
        } else if (result.isBottom() || fact.isTop()) {
        // No change in result fact
        } else {
            // Dataflow merge
            // (intersection of unconditional deref values)
            if (replacedUME_NONZERO_TRIP_LOOPS && result.resultsFromBackEdge) {
                result.backEdgeUpdateCount++;
                if (result.backEdgeUpdateCount < 10) {
                    if (DEBUG) {
                        System.out.println("\n Union update of " + System.idenreplacedyHashCode(result) + " due to backedge info");
                    }
                    result.unionWith(fact, vnaDataflow.getreplacedysis().getFactory());
                    return;
                }
            }
            result.mergeWith(fact, knownNonnullOnBranch, vnaDataflow.getreplacedysis().getFactory());
            if (DEBUG) {
                System.out.println("  updated: " + System.idenreplacedyHashCode(result));
                System.out.println("  result: " + result);
            }
        }
        if (DEBUG && isBackEdge && edge.getType() == EdgeTypes.IFCMP_EDGE) {
            System.out.println("  result: " + result);
        }
    }

    /**
     * Find out if any VNs in the source block contribute to unconditionally
     * dereferenced VNs in the target block. If so, the VN in the source block
     * is also unconditionally dereferenced, and we must propagate the target
     * VN's dereferences.
     *
     * @param fact
     *            a dataflow value
     * @param edge
     *            edge to check for merge input values
     * @return possibly-modified dataflow value
     */
    private UnconditionalValueDerefSet propagateDerefSetsToMergeInputValues(UnconditionalValueDerefSet fact, Edge edge) {
        ValueNumberFrame blockValueNumberFrame = vnaDataflow.getResultFact(edge.getSource());
        ValueNumberFrame targetValueNumberFrame = vnaDataflow.getStartFact(edge.getTarget());
        UnconditionalValueDerefSet originalFact = fact;
        fact = duplicateFact(fact);
        if (blockValueNumberFrame.isValid() && targetValueNumberFrame.isValid()) {
            int slots = 0;
            if (targetValueNumberFrame.getNumSlots() == blockValueNumberFrame.getNumSlots()) {
                slots = targetValueNumberFrame.getNumSlots();
            } else if (targetValueNumberFrame.getNumLocals() == blockValueNumberFrame.getNumLocals()) {
                slots = targetValueNumberFrame.getNumLocals();
            }
            if (slots > 0) {
                if (DEBUG) {
                    System.out.println("** Valid VNA frames for " + edge);
                    System.out.println("** Block : " + blockValueNumberFrame);
                    System.out.println("** Target: " + targetValueNumberFrame);
                }
                for (int i = 0; i < slots; i++) {
                    ValueNumber blockVN = blockValueNumberFrame.getValue(i);
                    ValueNumber targetVN = targetValueNumberFrame.getValue(i);
                    if (blockVN.equals(targetVN)) {
                        continue;
                    }
                    fact.clearDerefSet(blockVN);
                    if (originalFact.isUnconditionallyDereferenced(targetVN)) {
                        fact.setDerefSet(blockVN, originalFact.getUnconditionalDerefLocationSet(targetVN));
                    }
                }
                // for all slots
                for (ValueNumber blockVN : blockValueNumberFrame.valueNumbersForLoads()) {
                    AvailableLoad load = blockValueNumberFrame.getLoad(blockVN);
                    if (load == null) {
                        continue;
                    }
                    ValueNumber[] targetVNs = targetValueNumberFrame.getAvailableLoad(load);
                    if (targetVNs != null) {
                        for (ValueNumber targetVN : targetVNs) {
                            if (targetVN.hasFlag(ValueNumber.PHI_NODE) && fact.isUnconditionallyDereferenced(targetVN) && !fact.isUnconditionallyDereferenced(blockVN)) {
                                // Block VN is also dereferenced
                                // unconditionally.
                                AvailableLoad targetLoad = targetValueNumberFrame.getLoad(targetVN);
                                if (!load.equals(targetLoad)) {
                                    continue;
                                }
                                if (DEBUG) {
                                    System.out.println("** Copy vn derefs for " + load + " from " + targetVN + " --> " + blockVN);
                                    System.out.println("** block phi for " + System.idenreplacedyHashCode(blockValueNumberFrame) + " is " + blockValueNumberFrame.phiNodeForLoads);
                                    System.out.println("** target phi for " + System.idenreplacedyHashCode(targetValueNumberFrame) + " is " + targetValueNumberFrame.phiNodeForLoads);
                                }
                                fact.setDerefSet(blockVN, fact.getUnconditionalDerefLocationSet(targetVN));
                            }
                        }
                    }
                }
            }
        }
        if (DEBUG) {
            System.out.println("Target VNF: " + targetValueNumberFrame);
            System.out.println("Block VNF: " + blockValueNumberFrame);
            System.out.println("fact: " + fact);
        }
        fact.cleanDerefSet(null, blockValueNumberFrame);
        return fact;
    }

    /**
     * Return a duplicate of given dataflow fact.
     *
     * @param fact
     *            a dataflow fact
     * @return a duplicate of the input dataflow fact
     */
    private UnconditionalValueDerefSet duplicateFact(UnconditionalValueDerefSet fact) {
        UnconditionalValueDerefSet copyOfFact = createFact();
        copy(fact, copyOfFact);
        fact = copyOfFact;
        return fact;
    }

    /**
     * Clear deref sets of values if this edge is the non-null branch of an if
     * comparison.
     *
     * @param fact
     *            a datflow fact
     * @param edge
     *            edge to check
     * @return possibly-modified dataflow fact
     */
    @CheckForNull
    private ValueNumber findValueKnownNonnullOnBranch(UnconditionalValueDerefSet fact, Edge edge) {
        IsNullValueFrame invFrame = invDataflow.getResultFact(edge.getSource());
        if (!invFrame.isValid()) {
            return null;
        }
        IsNullConditionDecision decision = invFrame.getDecision();
        if (decision == null) {
            return null;
        }
        IsNullValue inv = decision.getDecision(edge.getType());
        if (inv == null || !inv.isDefinitelyNotNull()) {
            return null;
        }
        ValueNumber value = decision.getValue();
        if (DEBUG) {
            System.out.println("Value number " + value + " is known nonnull on " + edge);
        }
        return value;
    }

    /**
     * Determine whether dataflow should be propagated on given edge.
     *
     * @param edge
     *            the edge
     * @return true if dataflow should be propagated on the edge, false
     *         otherwise
     */
    private boolean isExceptionEdge(Edge edge) {
        boolean isExceptionEdge = edge.isExceptionEdge();
        if (isExceptionEdge) {
            if (DEBUG) {
                System.out.println("NOT Ignoring " + edge);
            }
            // false
            return true;
        }
        if (edge.getType() != EdgeTypes.FALL_THROUGH_EDGE) {
            return false;
        }
        InstructionHandle h = edge.getSource().getLastInstruction();
        return h != null && h.getInstruction() instanceof IFNONNULL && isNullCheck(h, methodGen.getConstantPool());
    }

    @Override
    public boolean same(UnconditionalValueDerefSet fact1, UnconditionalValueDerefSet fact2) {
        return fact1.resultsFromBackEdge || fact1.isSameAs(fact2);
    }

    @Override
    public void starreplacederation() {
    // System.out.println("replacedysis iteration in " +
    // methodGen.getClreplacedName() + " on " + methodGen.toString());
    }

    @Override
    public int getLastUpdateTimestamp(UnconditionalValueDerefSet fact) {
        return fact.getLastUpdateTimestamp();
    }

    @Override
    public void setLastUpdateTimestamp(UnconditionalValueDerefSet fact, int lastUpdate) {
        fact.setLastUpdateTimestamp(lastUpdate);
    }
    // public static void main(String[] args) throws Exception {
    // if (args.length != 1) {
    // System.err.println("Usage: " +
    // UnconditionalValueDerefreplacedysis.clreplaced.getName() + " <clreplacedfile>");
    // System.exit(1);
    // }
    // 
    // DataflowTestDriver<UnconditionalValueDerefSet,
    // UnconditionalValueDerefreplacedysis> driver =
    // new DataflowTestDriver<UnconditionalValueDerefSet,
    // UnconditionalValueDerefreplacedysis>() {
    // /* (non-Javadoc)
    // * @see
    // edu.umd.cs.findbugs.ba.DataflowTestDriver#createDataflow(edu.umd.cs.findbugs.ba.ClreplacedContext,
    // org.apache.bcel.clreplacedfile.Method)
    // */
    // @Override
    // public Dataflow<UnconditionalValueDerefSet,
    // UnconditionalValueDerefreplacedysis> createDataflow(ClreplacedContext
    // clreplacedContext, Method method) throws CFGBuilderException,
    // DataflowreplacedysisException {
    // return clreplacedContext.getUnconditionalValueDerefDataflow(method);
    // }
    // };
    // if (SystemProperties.getBoolean("forwardcfg")) {
    // driver.overrideIsForwards();
    // }
    // driver.execute(args[0]);
    // }
}

17 Source : TaintDataflowEngine.java
with GNU Lesser General Public License v3.0
from blackarbiter

@Override
public TaintDataflow replacedyze(IreplacedysisCache cache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    if (FindSecBugsGlobalConfig.getInstance().isDebugPrintInstructionVisited() || FindSecBugsGlobalConfig.getInstance().isDebugPrintInvocationVisited()) {
        System.out.println("==[ Method: " + descriptor.getName() + " ]==");
    }
    CFG cfg = cache.getMethodreplacedysis(CFG.clreplaced, descriptor);
    DepthFirstSearch dfs = cache.getMethodreplacedysis(DepthFirstSearch.clreplaced, descriptor);
    MethodGen methodGen = cache.getMethodreplacedysis(MethodGen.clreplaced, descriptor);
    Taintreplacedysis replacedysis = new Taintreplacedysis(methodGen, dfs, descriptor, taintConfig);
    TaintDataflow flow = new TaintDataflow(cfg, replacedysis);
    flow.execute();
    replacedysis.finishreplacedysis();
    if (CONFIG.isDebugOutputTaintConfigs() && writer != null) {
        TaintMethodConfig derivedConfig = taintConfig.get(getSlashedMethodName(methodGen));
        if (derivedConfig != null) {
            try {
                writer.append(getSlashedMethodName(methodGen) + ":" + derivedConfig + "\n");
                writer.flush();
            } catch (IOException ex) {
                replacedysisContext.logError("Cannot write derived configs", ex);
            }
        }
    }
    return flow;
}

17 Source : ObjectDeserializationDetector.java
with GNU Lesser General Public License v3.0
from blackarbiter

private void replacedyzeMethod(Method m, ClreplacedContext clreplacedContext) throws CFGBuilderException, DataflowreplacedysisException {
    MethodGen methodGen = clreplacedContext.getMethodGen(m);
    ConstantPoolGen cpg = clreplacedContext.getConstantPoolGen();
    CFG cfg = clreplacedContext.getCFG(m);
    if (methodGen == null || methodGen.getInstructionList() == null) {
        // No instruction .. nothing to do
        return;
    }
    for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
        Location location = i.next();
        Instruction inst = location.getHandle().getInstruction();
        // 
        if (inst instanceof InvokeInstruction) {
            // System.out.println(inst.getName());
            InvokeInstruction invoke = (InvokeInstruction) inst;
            String clreplacedName = invoke.getClreplacedName(cpg);
            if ("java.io.ObjectInputStream".equals(clreplacedName) || clreplacedName.contains("InputStream") || InterfaceUtils.isSubtype(clreplacedName, "java.io.ObjectInputStream")) {
                String methodName = invoke.getMethodName(cpg);
                if (OBJECT_INPUTSTREAM_READ_METHODS.contains(methodName)) {
                    JavaClreplaced clz = clreplacedContext.getJavaClreplaced();
                    bugReporter.reportBug(// 
                    new BugInstance(this, OBJECT_DESERIALIZATION_TYPE, HIGH_PRIORITY).addClreplaced(clz).addMethod(clz, m).addSourceLine(clreplacedContext, m, location));
                }
            }
        }
    }
}

17 Source : GoogleApiKeyDetector.java
with GNU Lesser General Public License v3.0
from blackarbiter

@Override
public void visitClreplacedContext(ClreplacedContext clreplacedContext) {
    JavaClreplaced javaClreplaced = clreplacedContext.getJavaClreplaced();
    boolean keyStringField = false;
    for (Field f : javaClreplaced.getFields()) {
        if (f.getName().equals("keyString")) {
            // The expected field name
            keyStringField = true;
            break;
        }
    }
    if (!keyStringField) {
        // No key field identify
        return;
    }
    // Clreplaced name left unchanged
    if (javaClreplaced.getClreplacedName().contains("UrlSigner")) {
        bugReporter.reportBug(// 
        new BugInstance(this, HARD_CODE_PreplacedWORD_TYPE, Priorities.NORMAL_PRIORITY).addClreplaced(javaClreplaced).addField(new FieldVariable(javaClreplaced.getClreplacedName(), "keyString", "Ljava/lang/String;")));
        return;
    }
    // Event if the clreplaced name was refactor, the method "signRequest" would probably be left.
    for (Method m : javaClreplaced.getMethods()) {
        MethodGen methodGen = clreplacedContext.getMethodGen(m);
        if (methodGen.getName().equals("signRequest")) {
            bugReporter.reportBug(// 
            new BugInstance(this, HARD_CODE_PreplacedWORD_TYPE, Priorities.NORMAL_PRIORITY).addClreplaced(javaClreplaced).addField(new FieldVariable(javaClreplaced.getClreplacedName(), "keyString", "")));
        }
    }
}

16 Source : ValueNumberDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public ValueNumberDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        throw new MethodUnprofitableException(descriptor);
    }
    DepthFirstSearch dfs = getDepthFirstSearch(replacedysisCache, descriptor);
    LoadedFieldSet loadedFieldSet = getLoadedFieldSet(replacedysisCache, descriptor);
    ValueNumberreplacedysis replacedysis = new ValueNumberreplacedysis(methodGen, dfs, loadedFieldSet, replacedysisContext.currentreplacedysisContext().getLookupFailureCallback());
    replacedysis.setMergeTree(new MergeTree(replacedysis.getFactory()));
    CFG cfg = getCFG(replacedysisCache, descriptor);
    ValueNumberDataflow vnaDataflow = new ValueNumberDataflow(cfg, replacedysis);
    vnaDataflow.execute();
    if (ClreplacedContext.DUMP_DATAFLOW_replacedYSIS) {
        TreeSet<Location> tree = new TreeSet<>();
        for (Iterator<Location> locs = cfg.locationIterator(); locs.hasNext(); ) {
            Location loc = locs.next();
            tree.add(loc);
        }
        System.out.println("\n\nValue number replacedysis for " + descriptor.getName() + descriptor.getSignature() + " {");
        for (Location loc : tree) {
            System.out.println("\nBefore: " + vnaDataflow.getFactAtLocation(loc));
            System.out.println("Location: " + loc);
            System.out.println("After: " + vnaDataflow.getFactAfterLocation(loc));
        }
        System.out.println("}\n");
    }
    return vnaDataflow;
}

16 Source : LiveLocalStoreDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public LiveLocalStoreDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        return null;
    }
    CFG cfg = getCFG(replacedysisCache, descriptor);
    ReverseDepthFirstSearch rdfs = getReverseDepthFirstSearch(replacedysisCache, descriptor);
    LiveLocalStorereplacedysis replacedysis = new LiveLocalStorereplacedysis(methodGen, rdfs, getDepthFirstSearch(replacedysisCache, descriptor));
    LiveLocalStoreDataflow dataflow = new LiveLocalStoreDataflow(cfg, replacedysis);
    dataflow.execute();
    if (ClreplacedContext.DUMP_DATAFLOW_replacedYSIS) {
        ClreplacedContext.dumpLiveLocalStoreDataflow(descriptor, cfg, dataflow);
    }
    return dataflow;
}

16 Source : IsNullValueDataflowFactory.java
with GNU Lesser General Public License v2.1
from spotbugs

/*
     * (non-Javadoc)
     *
     * @see
     * edu.umd.cs.findbugs.clreplacedfile.IreplacedysisEngine#replacedyze(edu.umd.cs.findbugs
     * .clreplacedfile.IreplacedysisCache, java.lang.Object)
     */
@Override
public IsNullValueDataflow replacedyze(IreplacedysisCache replacedysisCache, MethodDescriptor descriptor) throws CheckedreplacedysisException {
    MethodGen methodGen = getMethodGen(replacedysisCache, descriptor);
    if (methodGen == null) {
        throw new MethodUnprofitableException(descriptor);
    }
    CFG cfg = getCFG(replacedysisCache, descriptor);
    ValueNumberDataflow vnaDataflow = getValueNumberDataflow(replacedysisCache, descriptor);
    DepthFirstSearch dfs = getDepthFirstSearch(replacedysisCache, descriptor);
    replacedertionMethods replacedertionMethods = getreplacedertionMethods(replacedysisCache, descriptor.getClreplacedDescriptor());
    TypeDataflow typeDataflow = getTypeDataflow(replacedysisCache, descriptor);
    IsNullValuereplacedysis invreplacedysis = new IsNullValuereplacedysis(descriptor, methodGen, cfg, vnaDataflow, typeDataflow, dfs, replacedertionMethods);
    // Set return value and parameter databases
    invreplacedysis.setClreplacedAndMethod(new JavaClreplacedAndMethod(getJavaClreplaced(replacedysisCache, descriptor.getClreplacedDescriptor()), getMethod(replacedysisCache, descriptor)));
    IsNullValueDataflow invDataflow = new IsNullValueDataflow(cfg, invreplacedysis);
    invDataflow.execute();
    if (ClreplacedContext.DUMP_DATAFLOW_replacedYSIS) {
        invDataflow.dumpDataflow(invreplacedysis);
    }
    return invDataflow;
}

16 Source : ClassContext.java
with GNU Lesser General Public License v2.1
from spotbugs

@Nonnull
static public Set<Integer> getLoopExitBranches(Method method, MethodGen methodGen) {
    XMethod xmethod = XFactory.createXMethod(methodGen);
    if (cachedLoopExits().containsKey(xmethod)) {
        Set<Integer> result = cachedLoopExits().get(xmethod);
        if (result == null) {
            replacedysisContext.logError("Null cachedLoopExits for " + xmethod, new NullPointerException());
            replacedert false;
            return Collections.<Integer>emptySet();
        }
        return result;
    }
    Code code = method.getCode();
    if (code == null) {
        replacedert false;
        return Collections.<Integer>emptySet();
    }
    byte[] instructionList = code.getCode();
    Set<Integer> result = new HashSet<>();
    for (int i = 0; i < instructionList.length; i++) {
        if (checkForBranchExit(instructionList, i)) {
            result.add(i);
        }
    }
    if (result.size() == 0) {
        result = Collections.<Integer>emptySet();
    }
    cachedLoopExits().put(xmethod, result);
    return result;
}

16 Source : BetterCFGBuilder2.java
with GNU Lesser General Public License v2.1
from spotbugs

/**
 * Test driver.
 */
public static void main(String[] argv) throws Exception {
    if (argv.length != 1) {
        System.err.println("Usage: " + BetterCFGBuilder2.clreplaced.getName() + " <clreplaced file>");
        System.exit(1);
    }
    String methodName = SystemProperties.getProperty("cfgbuilder.method");
    JavaClreplaced jclreplaced = new ClreplacedParser(argv[0]).parse();
    ClreplacedGen clreplacedGen = new ClreplacedGen(jclreplaced);
    Method[] methodList = jclreplaced.getMethods();
    for (Method method : methodList) {
        if (method.isAbstract() || method.isNative()) {
            continue;
        }
        if (methodName != null && !method.getName().equals(methodName)) {
            continue;
        }
        MethodDescriptor descriptor = DescriptorFactory.instance().getMethodDescriptor(jclreplaced, method);
        MethodGen methodGen = new MethodGen(method, jclreplaced.getClreplacedName(), clreplacedGen.getConstantPool());
        CFGBuilder cfgBuilder = new BetterCFGBuilder2(descriptor, methodGen);
        cfgBuilder.build();
        CFG cfg = cfgBuilder.getCFG();
        CFGPrinter cfgPrinter = new CFGPrinter(cfg);
        System.out.println("---------------------------------------------------------------------");
        System.out.println("Method: " + SignatureConverter.convertMethodSignature(methodGen));
        System.out.println("---------------------------------------------------------------------");
        cfgPrinter.print(System.out);
    }
}

See More Examples