Java Code Examples for org.apache.bcel.generic.InstructionHandle#getInstruction()

The following examples show how to use org.apache.bcel.generic.InstructionHandle#getInstruction() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AssertionMethods.java    From spotbugs with GNU Lesser General Public License v2.1 6 votes vote down vote up
public boolean isAssertionHandle(InstructionHandle handle, ConstantPoolGen cpg) {
    Instruction ins = handle.getInstruction();
    if (isAssertionInstruction(ins, cpg)) {
        return true;
    }

    if (ins instanceof SIPUSH) {
        int v = ((SIPUSH) ins).getValue().intValue();
        if (v == 500) {
            Instruction next = handle.getNext().getInstruction();
            if (next instanceof INVOKEINTERFACE) {
                INVOKEINTERFACE iInterface = (INVOKEINTERFACE) next;
                String className = iInterface.getClassName(cpg);
                String fieldName = iInterface.getMethodName(cpg);
                if ("javax.servlet.http.HttpServletResponse".equals(className) && "setStatus".equals(fieldName)) {
                    return true;
                }

            }
        }
    }
    return false;
}
 
Example 2
Source File: CallListAnalysis.java    From spotbugs with GNU Lesser General Public License v2.1 6 votes vote down vote up
private static Map<InstructionHandle, Call> buildCallMap(CFG cfg, ConstantPoolGen cpg) {
    Map<InstructionHandle, Call> callMap = new HashMap<>();

    for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
        InstructionHandle handle = i.next().getHandle();
        Instruction ins = handle.getInstruction();

        if (ins instanceof InvokeInstruction) {
            InvokeInstruction inv = (InvokeInstruction) ins;
            Call call = new Call(inv.getClassName(cpg), inv.getName(cpg), inv.getSignature(cpg));
            callMap.put(handle, call);
        }
    }

    return callMap;
}
 
Example 3
Source File: StackDepthAnalysis.java    From spotbugs with GNU Lesser General Public License v2.1 6 votes vote down vote up
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, StackDepth fact)
        throws DataflowAnalysisException {
    Instruction ins = handle.getInstruction();
    int produced = ins.produceStack(cpg);
    int consumed = ins.consumeStack(cpg);
    if (produced == Const.UNPREDICTABLE || consumed == Const.UNPREDICTABLE) {
        throw new IllegalStateException("Unpredictable stack delta for instruction: " + handle);
    }
    int depth = fact.getDepth();
    depth += (produced - consumed);
    if (depth < 0) {
        fact.setDepth(BOTTOM);
    } else {
        fact.setDepth(depth);
    }
}
 
Example 4
Source File: Subroutines.java    From commons-bcel with Apache License 2.0 6 votes vote down vote up
/**
 * Sets the leaving RET instruction. Must be invoked after all instructions are added.
 * Must not be invoked for top-level 'subroutine'.
 */
void setLeavingRET() {
    if (localVariable == UNSET) {
        throw new AssertionViolatedException(
            "setLeavingRET() called for top-level 'subroutine' or forgot to set local variable first.");
    }
    InstructionHandle ret = null;
    for (final InstructionHandle actual : instructions) {
        if (actual.getInstruction() instanceof RET) {
            if (ret != null) {
                throw new StructuralCodeConstraintException(
                    "Subroutine with more then one RET detected: '"+ret+"' and '"+actual+"'.");
            }
            ret = actual;
        }
    }
    if (ret == null) {
        throw new StructuralCodeConstraintException("Subroutine without a RET detected.");
    }
    if (((RET) ret.getInstruction()).getIndex() != localVariable) {
        throw new StructuralCodeConstraintException(
            "Subroutine uses '"+ret+"' which does not match the correct local variable '"+localVariable+"'.");
    }
    theRET = ret;
}
 
Example 5
Source File: BetterCFGBuilder2.java    From spotbugs with GNU Lesser General Public License v2.1 6 votes vote down vote up
/**
 * @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$");
}
 
Example 6
Source File: FieldSetAnalysis.java    From spotbugs with GNU Lesser General Public License v2.1 5 votes vote down vote up
private void handleInstruction(InstructionHandle handle, BasicBlock basicBlock, FieldSet fact) {
    Instruction ins = handle.getInstruction();
    short opcode = ins.getOpcode();
    XField field;

    switch (opcode) {
    case Const.GETFIELD:
    case Const.GETSTATIC:
        field = lookupField(handle, (FieldInstruction) ins);
        if (field != null) {
            sawLoad(fact, field);
        }
        break;

    case Const.PUTFIELD:
    case Const.PUTSTATIC:
        field = lookupField(handle, (FieldInstruction) ins);
        if (field != null) {
            sawStore(fact, field);
        }
        break;

    case Const.INVOKEINTERFACE:
    case Const.INVOKESPECIAL:
    case Const.INVOKESTATIC:
    case Const.INVOKEVIRTUAL:
        // Assume that the called method assigns loads and stores all
        // possible fields
        fact.setBottom();
        break;
    default:
        break;
    }
}
 
Example 7
Source File: Subroutines.java    From commons-bcel with Apache License 2.0 5 votes vote down vote up
@Override
public Subroutine[] subSubs() {
    final Set<Subroutine> h = new HashSet<>();

    for (final InstructionHandle ih : instructions) {
        final Instruction inst = ih.getInstruction();
        if (inst instanceof JsrInstruction) {
            final InstructionHandle targ = ((JsrInstruction) inst).getTarget();
            h.add(getSubroutine(targ));
        }
    }
    final Subroutine[] ret = new Subroutine[h.size()];
    return h.toArray(ret);
}
 
Example 8
Source File: Stream.java    From spotbugs with GNU Lesser General Public License v2.1 5 votes vote down vote up
public boolean isStreamClose(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, ResourceValueFrame frame,
        RepositoryLookupFailureCallback lookupFailureCallback) {
    if (!mightCloseStream(basicBlock, handle, cpg)) {
        return false;
    }

    Instruction ins = handle.getInstruction();

    if ((ins instanceof INVOKEVIRTUAL) || (ins instanceof INVOKEINTERFACE)) {
        // Does this instruction close the stream?
        InvokeInstruction inv = (InvokeInstruction) ins;

        if (!frame.isValid() || !getInstanceValue(frame, inv, cpg).isInstance()) {
            return false;
        }

        // It's a close if the invoked class is any subtype of the stream
        // base class.
        // (Basically, we may not see the exact original stream class,
        // even though it's the same instance.)
        try {
            String classClosed = inv.getClassName(cpg);

            if (relatedType(classClosed)) {
                return true;
            }
            if ("java.io.ObjectOutput".equals(classClosed)) {
                return relatedType("java.io.ObjectOutputStream");
            } else if ("java.io.ObjectInput".equals(classClosed)) {
                return relatedType("java.io.ObjectInputStream");
            }
            return false;
        } catch (ClassNotFoundException e) {
            lookupFailureCallback.reportMissingClass(e);
            return false;
        }
    }

    return false;
}
 
Example 9
Source File: RedundantConditions.java    From spotbugs with GNU Lesser General Public License v2.1 5 votes vote down vote up
private int getIntValue(InstructionHandle handle) {
    Instruction instruction = handle.getInstruction();
    if (instruction instanceof ICONST) {
        return ((ICONST) instruction).getValue().intValue();
    }
    return -1;
}
 
Example 10
Source File: FindSqlInjection.java    From spotbugs with GNU Lesser General Public License v2.1 5 votes vote down vote up
private @CheckForNull InstructionHandle getPreviousInstruction(InstructionHandle handle, boolean skipNops) {
    while (handle.getPrev() != null) {
        handle = handle.getPrev();
        Instruction prevIns = handle.getInstruction();
        if (!(prevIns instanceof NOP && skipNops)) {
            return handle;
        }
    }
    return null;
}
 
Example 11
Source File: FindUseOfNonSerializableValue.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {
    MethodGen methodGen = classContext.getMethodGen(method);
    if (methodGen == null) {
        return;
    }
    BitSet bytecodeSet = classContext.getBytecodeSet(method);
    if (bytecodeSet == null) {
        return;
    }
    // We don't adequately model instanceof interfaces yet
    if (bytecodeSet.get(Const.INSTANCEOF) || bytecodeSet.get(Const.CHECKCAST)) {
        return;
    }
    CFG cfg = classContext.getCFG(method);
    TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
    ConstantPoolGen cpg = classContext.getConstantPoolGen();

    String sourceFile = classContext.getJavaClass().getSourceFileName();
    if (DEBUG) {
        String methodName = methodGen.getClassName() + "." + methodGen.getName();
        System.out.println("Checking " + methodName);
    }

    for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
        Location location = i.next();
        InstructionHandle handle = location.getHandle();
        Instruction ins = handle.getInstruction();

        Use use = getUse(cpg, ins);
        if (use == null) {
            continue;
        }

        TypeFrame frame = typeDataflow.getFactAtLocation(location);
        if (!frame.isValid()) {
            // This basic block is probably dead
            continue;
        }
        Type operandType = frame.getTopValue();

        if (operandType.equals(TopType.instance())) {
            // unreachable
            continue;
        }
        if (!(operandType instanceof ReferenceType)) {
            // Shouldn't happen - illegal bytecode
            continue;
        }
        ReferenceType refType = (ReferenceType) operandType;

        if (refType.equals(NullType.instance())) {
            continue;
        }

        try {

            double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(refType);

            if (isSerializable < 0.9) {
                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext,
                        methodGen, sourceFile, handle);
                ReferenceType problem = DeepSubtypeAnalysis.getLeastSerializableTypeComponent(refType);

                String pattern;
                switch (use) {
                case PASSED_TO_WRITE_OBJECT:
                    pattern = "DMI_NONSERIALIZABLE_OBJECT_WRITTEN";
                    double isRemote = DeepSubtypeAnalysis.isDeepRemote(refType);
                    if (isRemote >= 0.9) {
                        continue;
                    }
                    if (isSerializable < isRemote) {
                        isSerializable = isRemote;
                    }
                    break;
                case STORE_INTO_HTTP_SESSION:
                    pattern = "J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION";
                    break;
                default:
                    throw new IllegalStateException();
                }

                bugAccumulator.accumulateBug(new BugInstance(this, pattern,
                        isSerializable < 0.15 ? HIGH_PRIORITY : isSerializable > 0.5 ? LOW_PRIORITY : NORMAL_PRIORITY)
                                .addClassAndMethod(methodGen, sourceFile).addType(problem).describe(TypeAnnotation.FOUND_ROLE),
                        sourceLineAnnotation);

            }
        } catch (ClassNotFoundException e) {
            // ignore
        }
    }
}
 
Example 12
Source File: RedundantConditions.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
private int getPriority(MethodDescriptor methodDescriptor, RedundantCondition condition) {
    if (condition.isByType()) {
        // Skip reports which should be reported by another detector
        long number = condition.getNumber().longValue();
        switch (condition.getSignature()) {
        case "I":
            if (number == Integer.MIN_VALUE || number == Integer.MAX_VALUE) {
                // Will be reported as INT_VACUOUS_COMPARISON
                return IGNORE_PRIORITY;
            }
            break;
        case "C":
            if (number <= 0) {
                // Will be reported as INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE
                return IGNORE_PRIORITY;
            }
            break;
        case "B":
            if (number < Byte.MIN_VALUE || number >= Byte.MAX_VALUE) {
                // Will be reported as INT_BAD_COMPARISON_WITH_SIGNED_BYTE
                return IGNORE_PRIORITY;
            }
            break;
        default:
            break;
        }
    }
    int priority = condition.isDeadCodeUnreachable() ? HIGH_PRIORITY
            : condition.isBorder()
                    || condition.getSignature().equals("Z") ? LOW_PRIORITY : NORMAL_PRIORITY;
    // check for boolean conversion
    if (condition.getDeadCodeLocation() != null && condition.getLiveCodeLocation() != null && condition.isDeadCodeUnreachable()) {
        InstructionHandle deadHandle = condition.getDeadCodeLocation().getHandle();
        InstructionHandle liveHandle = condition.getLiveCodeLocation().getHandle();
        int deadValue = getIntValue(deadHandle);
        int liveValue = getIntValue(liveHandle);
        if ((deadValue == 0 && liveValue == 1) || (deadValue == 1 && liveValue == 0)) {
            InstructionHandle deadNext = deadHandle.getNext();
            InstructionHandle liveNext = liveHandle.getNext();
            if (deadNext != null && liveNext != null) {
                InstructionHandle middle, after;
                if (deadNext.getNext() == liveHandle) {
                    middle = deadNext;
                    after = liveNext;
                } else if (liveNext.getNext() == deadHandle) {
                    middle = liveNext;
                    after = deadNext;
                } else {
                    return priority;
                }
                if (!(middle.getInstruction() instanceof GOTO) || ((GOTO) middle.getInstruction()).getTarget() != after) {
                    return priority;
                }
                MethodGen methodGen;
                try {
                    methodGen = Global.getAnalysisCache().getMethodAnalysis(MethodGen.class, methodDescriptor);
                } catch (CheckedAnalysisException e) {
                    return priority;
                }
                InstructionHandle consumer = getConsumer(methodGen, after);
                Instruction consumerInst = consumer == null ? null : consumer.getInstruction();
                if (consumerInst != null) {
                    short opcode = consumerInst.getOpcode();
                    if (opcode == Const.IADD || opcode == Const.ISUB || opcode == Const.IMUL
                            || opcode == Const.ISHR || opcode == Const.ISHL || opcode == Const.IUSHR) {
                        // It's actually integer expression with explicit ? 1 : 0 or ? 0 : 1 operation
                        return priority;
                    }
                }
                if (condition.getSignature().equals("Z")) {
                    // Ignore !flag when flag value is known
                    return IGNORE_PRIORITY;
                }
                priority = condition.isBorder() ? LOW_PRIORITY : NORMAL_PRIORITY;
                if (consumerInst instanceof InvokeInstruction) {
                    ConstantPoolGen constantPool = methodGen.getConstantPool();
                    String methodName = ((InvokeInstruction) consumerInst).getMethodName(constantPool);
                    // Ignore values conditions used in assertion methods
                    if ((methodName.equals("assertTrue") || methodName.equals("checkArgument") || methodName.equals("isLegal")
                            || methodName.equals("isTrue"))) {
                        return liveValue == 1 ? condition.isBorder() ? IGNORE_PRIORITY : LOW_PRIORITY : HIGH_PRIORITY;
                    }
                    if ((methodName.equals("assertFalse") || methodName.equals("isFalse"))) {
                        return liveValue == 0 ? condition.isBorder() ? IGNORE_PRIORITY : LOW_PRIORITY : HIGH_PRIORITY;
                    }
                }
            }
        }
    }
    return priority;
}
 
Example 13
Source File: FindRefComparison.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
private void checkRefComparison(Location location, JavaClass jclass, Method method, MethodGen methodGen,
        RefComparisonTypeFrameModelingVisitor visitor, TypeDataflow typeDataflow,
        List<WarningWithProperties> stringComparisonList, List<WarningWithProperties> refComparisonList)
        throws DataflowAnalysisException {

    InstructionHandle handle = location.getHandle();

    TypeFrame frame = typeDataflow.getFactAtLocation(location);
    if (frame.getStackDepth() < 2) {
        throw new DataflowAnalysisException("Stack underflow", methodGen, handle);
    }

    int numSlots = frame.getNumSlots();
    Type lhsType = frame.getValue(numSlots - 2);
    Type rhsType = frame.getValue(numSlots - 1);

    if (lhsType instanceof NullType || rhsType instanceof NullType) {
        return;
    }
    if (lhsType instanceof ReferenceType && rhsType instanceof ReferenceType) {
        IncompatibleTypes result = IncompatibleTypes.getPriorityForAssumingCompatible(lhsType, rhsType, true);
        if (result != IncompatibleTypes.SEEMS_OK && result != IncompatibleTypes.UNCHECKED) {
            String sourceFile = jclass.getSourceFileName();

            boolean isAssertSame = handle.getInstruction() instanceof INVOKESTATIC;
            if (isAssertSame) {
                if (testingEnabled) {
                    bugAccumulator.accumulateBug(
                            new BugInstance(this, "TESTING", result.getPriority())
                                    .addClassAndMethod(methodGen, sourceFile)
                                    .addString("Calling assertSame with two distinct objects")
                                    .addFoundAndExpectedType(rhsType, lhsType)
                                    .addSomeSourceForTopTwoStackValues(classContext, method, location),
                            SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
                }
            } else {
                bugAccumulator.accumulateBug(
                        new BugInstance(this, "EC_UNRELATED_TYPES_USING_POINTER_EQUALITY", result.getPriority())
                                .addClassAndMethod(methodGen, sourceFile).addFoundAndExpectedType(rhsType, lhsType)
                                .addSomeSourceForTopTwoStackValues(classContext, method, location),
                        SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
            }
            return;
        }
        if (lhsType.equals(Type.OBJECT) && rhsType.equals(Type.OBJECT)) {
            return;
        }
        String lhs = SignatureConverter.convert(lhsType.getSignature());
        String rhs = SignatureConverter.convert(rhsType.getSignature());

        if (Values.DOTTED_JAVA_LANG_STRING.equals(lhs) || Values.DOTTED_JAVA_LANG_STRING.equals(rhs)) {
            handleStringComparison(jclass, method, methodGen, visitor, stringComparisonList, location, lhsType, rhsType);
        } else if (suspiciousSet.contains(lhs)) {
            handleSuspiciousRefComparison(jclass, method, methodGen, refComparisonList, location, lhs,
                    (ReferenceType) lhsType, (ReferenceType) rhsType);
        } else if (suspiciousSet.contains(rhs)) {
            handleSuspiciousRefComparison(jclass, method, methodGen, refComparisonList, location, rhs,
                    (ReferenceType) lhsType, (ReferenceType) rhsType);
        }
    }
}
 
Example 14
Source File: FindUnreleasedLock.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock) throws DataflowAnalysisException {
    final Instruction ins = handle.getInstruction();
    final ConstantPoolGen cpg = getCPG();
    final ResourceValueFrame frame = getFrame();

    int status = -1;

    if (DEBUG) {
        System.out.println("PC : " + handle.getPosition() + " " + ins);
    }
    if (DEBUG && ins instanceof InvokeInstruction) {
        System.out.println("  " + ins.toString(cpg.getConstantPool()));
    }
    if (DEBUG) {
        System.out.println("resource frame before instruction: " + frame.toString());
    }

    // Is a lock acquired or released by this instruction?
    Location creationPoint = lock.getLocation();
    if (handle == creationPoint.getHandle() && basicBlock == creationPoint.getBasicBlock()) {
        status = ResourceValueFrame.OPEN;
        if (DEBUG) {
            System.out.println("OPEN");
        }
    } else if (resourceTracker.isResourceClose(basicBlock, handle, cpg, lock, frame)) {
        status = ResourceValueFrame.CLOSED;
        if (DEBUG) {
            System.out.println("CLOSE");
        }
    }

    // Model use of instance values in frame slots
    analyzeInstruction(ins);

    final int updatedNumSlots = frame.getNumSlots();

    // Mark any appearances of the lock value in the ResourceValueFrame.
    ValueNumberFrame vnaFrame = vnaDataflow.getFactAfterLocation(new Location(handle, basicBlock));
    if (DEBUG) {
        System.out.println("vna frame after instruction: " + vnaFrame.toString());
        System.out.println("Lock value number: " + lock.getLockValue());
        if (lock.getLockValue().hasFlag(ValueNumber.RETURN_VALUE)) {
            System.out.println("is return value");
        }
    }

    for (int i = 0; i < updatedNumSlots; ++i) {
        if (DEBUG) {
            System.out.println("Slot " + i);
            System.out.println("  Lock value number: " + vnaFrame.getValue(i));
            if (vnaFrame.getValue(i).hasFlag(ValueNumber.RETURN_VALUE)) {
                System.out.println("  is return value");
            }
        }
        if (vnaFrame.fuzzyMatch(lock.getLockValue(), vnaFrame.getValue(i))) {
            if (DEBUG) {
                System.out.println("Saw lock value!");
            }
            frame.setValue(i, ResourceValue.instance());
        }
    }

    // If needed, update frame status
    if (status != -1) {
        frame.setStatus(status);
    }
    if (DEBUG) {
        System.out.println("resource frame after instruction: " + frame.toString());
    }

}
 
Example 15
Source File: Pass3aVerifier.java    From commons-bcel with Apache License 2.0 4 votes vote down vote up
/**
 * These are the checks if constraints are satisfied which are described in the
 * Java Virtual Machine Specification, Second Edition as Static Constraints on
 * the instructions of Java Virtual Machine Code (chapter 4.8.1).
 *
 * @throws StaticCodeConstraintException if the verification fails.
 */
private void pass3StaticInstructionChecks() {

    // Code array must not be empty:
    // Enforced in pass 2 (also stated in the static constraints of the Code
    // array in vmspec2), together with pass 1 (reading code_length bytes and
    // interpreting them as code[]). So this must not be checked again here.

    if (code.getCode().length >= Const.MAX_CODE_SIZE) {// length must be LESS than the max
        throw new StaticCodeInstructionConstraintException(
            "Code array in code attribute '"+code+"' too big: must be smaller than "+Const.MAX_CODE_SIZE+"65536 bytes.");
    }

    // First opcode at offset 0: okay, that's clear. Nothing to do.

    // Only instances of the instructions documented in Section 6.4 may appear in
    // the code array.

    // For BCEL's sake, we cannot handle WIDE stuff, but hopefully BCEL does its job right :)

    // The last byte of the last instruction in the code array must be the byte at index
    // code_length-1 : See the do_verify() comments. We actually don't iterate through the
    // byte array, but use an InstructionList so we cannot check for this. But BCEL does
    // things right, so it's implicitly okay.

    // TODO: Check how BCEL handles (and will handle) instructions like IMPDEP1, IMPDEP2,
    //       BREAKPOINT... that BCEL knows about but which are illegal anyway.
    //       We currently go the safe way here.
    InstructionHandle ih = instructionList.getStart();
    while (ih != null) {
        final Instruction i = ih.getInstruction();
        if (i instanceof IMPDEP1) {
            throw new StaticCodeInstructionConstraintException(
                "IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
        }
        if (i instanceof IMPDEP2) {
            throw new StaticCodeInstructionConstraintException(
                "IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
        }
        if (i instanceof BREAKPOINT) {
            throw new StaticCodeInstructionConstraintException(
                "BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM use!");
        }
        ih = ih.getNext();
    }

    // The original verifier seems to do this check here, too.
    // An unreachable last instruction may also not fall through the
    // end of the code, which is stupid -- but with the original
    // verifier's subroutine semantics one cannot predict reachability.
    final Instruction last = instructionList.getEnd().getInstruction();
    if (! ((last instanceof ReturnInstruction)    ||
                (last instanceof RET)                                ||
                (last instanceof GotoInstruction)            ||
                (last instanceof ATHROW) )) {
        throw new StaticCodeInstructionConstraintException(
            "Execution must not fall off the bottom of the code array."+
            " This constraint is enforced statically as some existing verifiers do"+
                    " - so it may be a false alarm if the last instruction is not reachable.");
    }
}
 
Example 16
Source File: FindMismatchedWaitOrNotify.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException {

        MethodGen methodGen = classContext.getMethodGen(method);
        if (methodGen == null) {
            return;
        }
        ConstantPoolGen cpg = methodGen.getConstantPool();
        CFG cfg = classContext.getCFG(method);
        ValueNumberDataflow vnaDataflow = classContext.getValueNumberDataflow(method);
        LockDataflow dataflow = classContext.getLockDataflow(method);

        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
            Location location = i.next();

            InstructionHandle handle = location.getHandle();

            Instruction ins = handle.getInstruction();
            if (!(ins instanceof INVOKEVIRTUAL)) {
                continue;
            }
            INVOKEVIRTUAL inv = (INVOKEVIRTUAL) ins;

            String methodName = inv.getName(cpg);
            String methodSig = inv.getSignature(cpg);

            if (Hierarchy.isMonitorWait(methodName, methodSig) || Hierarchy.isMonitorNotify(methodName, methodSig)) {
                int numConsumed = inv.consumeStack(cpg);
                if (numConsumed == Const.UNPREDICTABLE) {
                    throw new DataflowAnalysisException("Unpredictable stack consumption", methodGen, handle);
                }

                ValueNumberFrame frame = vnaDataflow.getFactAtLocation(location);
                if (!frame.isValid()) {
                    // Probably dead code
                    continue;
                }
                if (frame.getStackDepth() - numConsumed < 0) {
                    throw new DataflowAnalysisException("Stack underflow", methodGen, handle);
                }
                ValueNumber ref = frame.getValue(frame.getNumSlots() - numConsumed);
                LockSet lockSet = dataflow.getFactAtLocation(location);
                int lockCount = lockSet.getLockCount(ref.getNumber());

                if (lockCount == 0) {
                    Collection<ValueNumber> lockedValueNumbers = lockSet.getLockedValueNumbers(frame);
                    boolean foundMatch = false;
                    for (ValueNumber v : lockedValueNumbers) {
                        if (frame.veryFuzzyMatch(ref, v)) {
                            foundMatch = true;
                            break;
                        }
                    }

                    if (!foundMatch) {

                        String type = "wait".equals(methodName) ? "MWN_MISMATCHED_WAIT" : "MWN_MISMATCHED_NOTIFY";
                        String sourceFile = classContext.getJavaClass().getSourceFileName();
                        // Report as medium priority only if the method is
                        // public.
                        // Non-public methods may be properly locked in a
                        // calling context.
                        int priority = method.isPublic() ? NORMAL_PRIORITY : LOW_PRIORITY;

                        bugAccumulator.accumulateBug(
                                new BugInstance(this, type, priority).addClassAndMethod(methodGen, sourceFile),
                                SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle));
                    }
                }
            }
        }
        bugAccumulator.reportAccumulatedBugs();
    }
 
Example 17
Source File: Subroutines.java    From commons-bcel with Apache License 2.0 4 votes vote down vote up
@Override
public int[] getAccessedLocalsIndices() {
    //TODO: Implement caching.
    final Set<Integer> acc = new HashSet<>();
    if (theRET == null && this != getTopLevel()) {
        throw new AssertionViolatedException(
            "This subroutine object must be built up completely before calculating accessed locals.");
    }
    {
        for (final InstructionHandle ih : instructions) {
            // RET is not a LocalVariableInstruction in the current version of BCEL.
            if (ih.getInstruction() instanceof LocalVariableInstruction || ih.getInstruction() instanceof RET) {
                final int idx = ((IndexedInstruction) (ih.getInstruction())).getIndex();
                acc.add(Integer.valueOf(idx));
                // LONG? DOUBLE?.
                try{
                    // LocalVariableInstruction instances are typed without the need to look into
                    // the constant pool.
                    if (ih.getInstruction() instanceof LocalVariableInstruction) {
                        final int s = ((LocalVariableInstruction) ih.getInstruction()).getType(null).getSize();
                        if (s==2) {
                            acc.add(Integer.valueOf(idx+1));
                        }
                    }
                }
                catch(final RuntimeException re) {
                    throw new AssertionViolatedException("BCEL did not like NULL as a ConstantPoolGen object.", re);
                }
            }
        }
    }

    {
        final int[] ret = new int[acc.size()];
        int j=-1;
        for (final Integer accessedLocal : acc) {
            j++;
            ret[j] = accessedLocal.intValue();
        }
        return ret;
    }
}
 
Example 18
Source File: UnconditionalValueDerefAnalysis.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
@Override
public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, UnconditionalValueDerefSet fact)
        throws DataflowAnalysisException {

    Instruction instruction = handle.getInstruction();
    if (fact.isTop()) {
        return;
    }
    Location location = new Location(handle, basicBlock);

    // If this is a call to an assertion method,
    // change the dataflow value to be TOP.
    // We don't want to report future derefs that would
    // be guaranteed only if the assertion methods
    // returns normally.
    // TODO: at some point, evaluate whether we should revisit this
    if (isAssertion(handle) // || handle.getInstruction() instanceof ATHROW
    ) {
        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.
        // Assume 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);
    }

}
 
Example 19
Source File: IfNull.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
@Override
public boolean acceptBranch(Edge edge, InstructionHandle source) {
    boolean isIfNull = (source.getInstruction() instanceof IFNULL);
    return edge.getType() == (isIfNull ? IFCMP_EDGE : FALL_THROUGH_EDGE);
}
 
Example 20
Source File: XmlStreamReaderDetector.java    From Android_Code_Arbiter with GNU Lesser General Public License v3.0 4 votes vote down vote up
@Override
public void sawOpcode(int seen) {
    if (seen != Constants.INVOKEVIRTUAL) {
        return;
    }
    String fullClassName = getClassConstantOperand();
    String method = getNameConstantOperand();

    //The method call is doing XML parsing (see class javadoc)
    if (fullClassName.equals("javax/xml/stream/XMLInputFactory") &&
            method.equals("createXMLStreamReader")) {
        ClassContext classCtx = getClassContext();
        ConstantPoolGen cpg = classCtx.getConstantPoolGen();
        CFG cfg;
        try {
            cfg = classCtx.getCFG(getMethod());
        } catch (CFGBuilderException e) {
            AnalysisContext.logError("Cannot get CFG", e);
            return;
        }
        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
            Location location = i.next();
            Instruction inst = location.getHandle().getInstruction();

            //DTD disallow
            //XMLInputFactory.setProperty
            if (inst instanceof org.apache.bcel.generic.INVOKEVIRTUAL) {
                InvokeInstruction invoke = (InvokeInstruction) inst;
                if ("setProperty".equals(invoke.getMethodName(cpg))) {
                    org.apache.bcel.generic.LDC loadConst = ByteCode.getPrevInstruction(location.getHandle(), LDC.class);
                    if (loadConst != null) {
                        if (PROPERTY_SUPPORT_DTD.equals(loadConst.getValue(cpg)) || PROPERTY_IS_SUPPORTING_EXTERNAL_ENTITIES.equals(loadConst.getValue(cpg))){
                            InstructionHandle prev1 = location.getHandle().getPrev();
                            InstructionHandle prev2 = prev1.getPrev();
                            //Case where the boolean is wrapped like : Boolean.valueOf(true) : 2 instructions
                            if (invokeInstruction().atClass("java.lang.Boolean").atMethod("valueOf").matches(prev1.getInstruction(),cpg)) {
                                if (prev2.getInstruction() instanceof ICONST) {
                                    Integer valueWrapped = ByteCode.getConstantInt(prev2);
                                    if (valueWrapped != null && valueWrapped.equals(0)) { //Value is false
                                        return; //Safe feature is disable
                                    }
                                }
                            }
                            //Case where the boolean is declared as : Boolean.FALSE
                            else if (prev1.getInstruction() instanceof org.apache.bcel.generic.GETSTATIC) {
                                org.apache.bcel.generic.GETSTATIC getstatic = (org.apache.bcel.generic.GETSTATIC) prev1.getInstruction();
                                if (getstatic.getClassType(cpg).getClassName().equals("java.lang.Boolean") &&
                                        getstatic.getFieldName(cpg).equals("FALSE")) {
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
        //Raise a bug
        bugReporter.reportBug(new BugInstance(this, XXE_XMLSTREAMREADER_TYPE, Priorities.NORMAL_PRIORITY) //
                .addClass(this).addMethod(this).addSourceLine(this));
    }
}