Search in sources :

Example 11 with XMethod

use of edu.umd.cs.findbugs.ba.XMethod in project wcomponents by BorderTech.

the class CheckExpectedWarningsCustom method visitClass.

/**
 * {@inheritDoc}
 */
@Override
public void visitClass(final ClassDescriptor classDescriptor) throws CheckedAnalysisException {
    if (reporter == null) {
        if (!warned) {
            System.err.println("*** NOTE ***: CheckExpectedWarnings disabled because bug reporter doesn't use a BugCollection");
            warned = true;
        }
        return;
    }
    if (warningsByMethod == null) {
        // 
        // Build index of all warnings reported so far, by method.
        // Because this detector runs in a later pass than any
        // reporting detector, all warnings should have been
        // produced by this point.
        // 
        warningsByMethod = new HashMap<>();
        warningsByField = new HashMap<>();
        warningsByClass = new HashMap<>();
        BugCollection bugCollection = reporter.getBugCollection();
        for (Iterator<BugInstance> i = bugCollection.iterator(); i.hasNext(); ) {
            BugInstance warning = i.next();
            MethodAnnotation method = warning.getPrimaryMethod();
            FieldAnnotation field = warning.getPrimaryField();
            ClassAnnotation clazz = warning.getPrimaryClass();
            if (method != null) {
                MethodDescriptor methodDesc = method.toXMethod().getMethodDescriptor();
                Collection<BugInstance> warnings = warningsByMethod.get(methodDesc);
                if (warnings == null) {
                    warnings = new LinkedList<>();
                    warningsByMethod.put(methodDesc, warnings);
                }
                warnings.add(warning);
            } else if (field != null) {
                FieldDescriptor fieldDesc = XFactory.createXField(field).getFieldDescriptor();
                Collection<BugInstance> warnings = warningsByField.get(fieldDesc);
                if (warnings == null) {
                    warnings = new LinkedList<>();
                    warningsByField.put(fieldDesc, warnings);
                }
                warnings.add(warning);
            } else if (clazz != null) {
                ClassDescriptor classDesc = DescriptorFactory.createClassDescriptorFromDottedClassName(clazz.getClassName());
                Collection<BugInstance> warnings = warningsByClass.get(classDesc);
                if (warnings == null) {
                    warnings = new LinkedList<>();
                    warningsByClass.put(classDesc, warnings);
                }
                warnings.add(warning);
            }
        }
        // 
        // Based on enabled detectors, figure out which bug codes
        // could possibly be reported. Don't complain about
        // expected warnings that would be produced by detectors
        // that aren't enabled.
        // 
        possibleBugCodes = new HashSet<>();
        ExecutionPlan executionPlan = Global.getAnalysisCache().getDatabase(ExecutionPlan.class);
        for (Iterator<AnalysisPass> i = executionPlan.passIterator(); i.hasNext(); ) {
            AnalysisPass pass = i.next();
            for (Iterator<DetectorFactory> j = pass.iterator(); j.hasNext(); ) {
                DetectorFactory factory = j.next();
                Collection<BugPattern> reportedPatterns = factory.getReportedBugPatterns();
                for (BugPattern pattern : reportedPatterns) {
                    possibleBugCodes.add(pattern.getAbbrev());
                }
            }
        }
        if (DEBUG) {
            log("CEW: possible warnings are " + possibleBugCodes);
        }
    }
    XClass xclass = Global.getAnalysisCache().getClassAnalysis(XClass.class, classDescriptor);
    for (XMethod xmethod : xclass.getXMethods()) {
        if (DEBUG) {
            log("CEW: checking " + xmethod.toString());
        }
        check(xmethod, expectWarning, true);
        check(xmethod, noWarning, false);
    }
    for (XField xfield : xclass.getXFields()) {
        if (DEBUG) {
            log("CEW: checking " + xfield.toString());
        }
        check(xfield, expectWarning, true);
        check(xfield, noWarning, false);
    }
    check(xclass, expectWarning, true);
    check(xclass, noWarning, false);
}
Also used : ClassDescriptor(edu.umd.cs.findbugs.classfile.ClassDescriptor) XClass(edu.umd.cs.findbugs.ba.XClass) FieldDescriptor(edu.umd.cs.findbugs.classfile.FieldDescriptor) ExecutionPlan(edu.umd.cs.findbugs.plan.ExecutionPlan) XMethod(edu.umd.cs.findbugs.ba.XMethod) MethodDescriptor(edu.umd.cs.findbugs.classfile.MethodDescriptor) LinkedList(java.util.LinkedList) XField(edu.umd.cs.findbugs.ba.XField) Collection(java.util.Collection) AnalysisPass(edu.umd.cs.findbugs.plan.AnalysisPass)

Example 12 with XMethod

use of edu.umd.cs.findbugs.ba.XMethod in project fb-contrib by mebigfatguy.

the class SillynessPotPourri method getTrimUserValue.

@Nullable
private SPPUserValue getTrimUserValue() {
    if (stack.getStackDepth() == 0) {
        return null;
    }
    OpcodeStack.Item item = stack.getStackItem(0);
    int reg = item.getRegisterNumber();
    if (reg >= 0) {
        return new SPPUserValue(SPPMethod.TRIM, String.valueOf(reg));
    }
    XField field = item.getXField();
    if (field != null) {
        return new SPPUserValue(SPPMethod.TRIM, field.getName());
    }
    XMethod method = item.getReturnValueOf();
    if (method != null) {
        return new SPPUserValue(SPPMethod.TRIM, method.getName());
    }
    return new SPPUserValue(SPPMethod.TRIM);
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) XField(edu.umd.cs.findbugs.ba.XField) XMethod(edu.umd.cs.findbugs.ba.XMethod) Nullable(javax.annotation.Nullable)

Example 13 with XMethod

use of edu.umd.cs.findbugs.ba.XMethod in project fb-contrib by mebigfatguy.

the class StackedTryBlocks method sawOpcode.

/**
 * overrides the visitor to document what catch blocks do with regard to rethrowing the exceptions, and if the message is a static message
 *
 * @param seen
 *            the currently parsed opcode
 */
@Override
public void sawOpcode(int seen) {
    String message = null;
    try {
        stack.precomputation(this);
        if ((seen == Const.TABLESWITCH) || (seen == Const.LOOKUPSWITCH)) {
            int pc = getPC();
            for (int offset : getSwitchOffsets()) {
                transitionPoints.set(pc + offset);
            }
            transitionPoints.set(pc + getDefaultSwitchOffset());
        } else if (isBranch(seen) && (getBranchOffset() < 0)) {
            // throw out try blocks in loops, this could cause false
            // negatives
            // with two try/catches in one loop, but more unlikely
            Iterator<TryBlock> it = blocks.iterator();
            int target = getBranchTarget();
            while (it.hasNext()) {
                TryBlock block = it.next();
                if (block.getStartPC() >= target) {
                    it.remove();
                }
            }
        }
        int pc = getPC();
        TryBlock block = findBlockWithStart(pc);
        if (block != null) {
            inBlocks.add(block);
            block.setState(TryBlock.State.IN_TRY);
        }
        if (inBlocks.isEmpty()) {
            return;
        }
        TryBlock innerBlock = inBlocks.get(inBlocks.size() - 1);
        int nextPC = getNextPC();
        if (innerBlock.atHandlerPC(nextPC)) {
            if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) {
                innerBlock.setEndHandlerPC(getBranchTarget());
            } else {
                inBlocks.remove(innerBlock);
                blocks.remove(innerBlock);
            }
        } else if (innerBlock.atHandlerPC(pc)) {
            innerBlock.setState(TryBlock.State.IN_CATCH);
        } else if (innerBlock.atEndHandlerPC(pc)) {
            inBlocks.remove(inBlocks.size() - 1);
            innerBlock.setState(TryBlock.State.AFTER);
        }
        if (transitionPoints.get(nextPC)) {
            if (innerBlock.inCatch() && (innerBlock.getEndHandlerPC() > nextPC)) {
                innerBlock.setEndHandlerPC(nextPC);
            }
        }
        if (innerBlock.inCatch()) {
            if (((seen >= Const.IFEQ) && ((seen <= Const.RET))) || (seen == Const.GOTO_W) || OpcodeUtils.isReturn(seen)) {
                blocks.remove(innerBlock);
                inBlocks.remove(inBlocks.size() - 1);
            } else if (seen == Const.ATHROW) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    XMethod xm = item.getReturnValueOf();
                    if (xm != null) {
                        innerBlock.setThrowSignature(xm.getSignature());
                    }
                    innerBlock.setExceptionSignature(item.getSignature());
                    innerBlock.setMessage((String) item.getUserValue());
                } else {
                    inBlocks.remove(inBlocks.size() - 1);
                    innerBlock.setState(TryBlock.State.AFTER);
                }
            } else if ((seen == Const.INVOKESPECIAL) && Values.CONSTRUCTOR.equals(getNameConstantOperand())) {
                String cls = getClassConstantOperand();
                JavaClass exCls = Repository.lookupClass(cls);
                if (exCls.instanceOf(THROWABLE_CLASS)) {
                    String signature = getSigConstantOperand();
                    List<String> types = SignatureUtils.getParameterSignatures(signature);
                    if (!types.isEmpty()) {
                        if (Values.SIG_JAVA_LANG_STRING.equals(types.get(0)) && (stack.getStackDepth() >= types.size())) {
                            OpcodeStack.Item item = stack.getStackItem(types.size() - 1);
                            message = (String) item.getConstant();
                            if (message == null) {
                                message = "____UNKNOWN____" + System.identityHashCode(item);
                            }
                        }
                    } else {
                        message = "";
                    }
                }
            }
        }
    } catch (ClassNotFoundException cnfe) {
        bugReporter.reportMissingClass(cnfe);
    } finally {
        stack.sawOpcode(this, seen);
        if ((message != null) && (stack.getStackDepth() > 0)) {
            OpcodeStack.Item item = stack.getStackItem(0);
            item.setUserValue(message);
        }
    }
}
Also used : JavaClass(org.apache.bcel.classfile.JavaClass) OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) XMethod(edu.umd.cs.findbugs.ba.XMethod) Iterator(java.util.Iterator) ToString(com.mebigfatguy.fbcontrib.utils.ToString)

Example 14 with XMethod

use of edu.umd.cs.findbugs.ba.XMethod in project fb-contrib by mebigfatguy.

the class StackedTryBlocks method visitCode.

/**
 * overrides the visitor to look for 'idea' try catch blocks to find issues specifically, method needs two or more try catch blocks that only catch one
 * exception type.
 *
 * @param obj
 *            the currently parsed code object
 */
@Override
public void visitCode(Code obj) {
    try {
        XMethod xMethod = getXMethod();
        if (xMethod != null) {
            String[] tes = xMethod.getThrownExceptions();
            Set<String> thrownExceptions = new HashSet<>(Arrays.<String>asList((tes == null) ? new String[0] : tes));
            blocks = new ArrayList<>();
            inBlocks = new ArrayList<>();
            transitionPoints = new BitSet();
            CodeException[] ces = obj.getExceptionTable();
            for (CodeException ce : ces) {
                TryBlock tb = new TryBlock(ce);
                int existingBlock = blocks.indexOf(tb);
                if (existingBlock >= 0) {
                    tb = blocks.get(existingBlock);
                    tb.addCatchType(ce);
                } else {
                    blocks.add(tb);
                }
            }
            Iterator<TryBlock> it = blocks.iterator();
            while (it.hasNext()) {
                TryBlock block = it.next();
                if (block.hasMultipleHandlers() || block.isFinally() || block.catchIsThrown(getConstantPool(), thrownExceptions)) {
                    it.remove();
                }
            }
            if (blocks.size() > 1) {
                stack.resetForMethodEntry(this);
                super.visitCode(obj);
                if (blocks.size() > 1) {
                    TryBlock firstBlock = blocks.get(0);
                    for (int i = 1; i < blocks.size(); i++) {
                        TryBlock secondBlock = blocks.get(i);
                        if (!blocksSplitAcrossTransitions(firstBlock, secondBlock) && (firstBlock.getCatchType() == secondBlock.getCatchType()) && firstBlock.getThrowSignature().equals(secondBlock.getThrowSignature()) && firstBlock.getMessage().equals(secondBlock.getMessage()) && firstBlock.getExceptionSignature().equals(secondBlock.getExceptionSignature())) {
                            bugReporter.reportBug(new BugInstance(this, BugType.STB_STACKED_TRY_BLOCKS.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLineRange(this, firstBlock.getStartPC(), firstBlock.getEndHandlerPC()).addSourceLineRange(this, secondBlock.getStartPC(), secondBlock.getEndHandlerPC()));
                        }
                        firstBlock = secondBlock;
                    }
                }
            }
        }
    } finally {
        blocks = null;
        inBlocks = null;
        transitionPoints = null;
    }
}
Also used : CodeException(org.apache.bcel.classfile.CodeException) BitSet(java.util.BitSet) BugInstance(edu.umd.cs.findbugs.BugInstance) ToString(com.mebigfatguy.fbcontrib.utils.ToString) XMethod(edu.umd.cs.findbugs.ba.XMethod) HashSet(java.util.HashSet)

Example 15 with XMethod

use of edu.umd.cs.findbugs.ba.XMethod in project fb-contrib by mebigfatguy.

the class PossiblyRedundantMethodCalls method sawOpcode.

/**
 * implements the visitor to look for repetitive calls to the same method on the same object using the same constant parameters. These methods must return a
 * value.
 *
 * @param seen
 *            the opcode of the currently parsed instruction
 */
@Override
public void sawOpcode(int seen) {
    String userValue = null;
    try {
        stack.precomputation(this);
        int pc = getPC();
        if (branchTargets.get(pc)) {
            localMethodCalls.clear();
            fieldMethodCalls.clear();
            branchTargets.clear(pc);
        }
        if (((seen >= Const.IFEQ) && (seen <= Const.GOTO)) || ((seen >= Const.IFNULL) && (seen <= Const.GOTO_W))) {
            branchTargets.set(getBranchTarget());
        } else if ((seen == Const.TABLESWITCH) || (seen == Const.LOOKUPSWITCH)) {
            int[] offsets = getSwitchOffsets();
            for (int offset : offsets) {
                branchTargets.set(offset + pc);
            }
            branchTargets.set(getDefaultSwitchOffset() + pc);
        } else if (OpcodeUtils.isAStore(seen)) {
            localMethodCalls.remove(Integer.valueOf(RegisterUtils.getAStoreReg(this, seen)));
        } else if (seen == Const.PUTFIELD) {
            String fieldSource = "";
            if (stack.getStackDepth() > 0) {
                OpcodeStack.Item item = stack.getStackItem(0);
                fieldSource = (String) item.getUserValue();
                if (fieldSource == null) {
                    fieldSource = "";
                }
            }
            fieldMethodCalls.remove(new FieldInfo(fieldSource, getNameConstantOperand()));
        } else if (seen == Const.GETFIELD) {
            if (stack.getStackDepth() > 0) {
                OpcodeStack.Item item = stack.getStackItem(0);
                userValue = (String) item.getUserValue();
                if (userValue == null) {
                    int reg = item.getRegisterNumber();
                    if (reg >= 0) {
                        userValue = String.valueOf(reg);
                    } else {
                        XField xf = item.getXField();
                        if (xf != null) {
                            userValue = xf.getName();
                        }
                    }
                }
            }
        } else if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKESTATIC)) {
            String className = getClassConstantOperand();
            String methodName = getNameConstantOperand();
            String signature = getSigConstantOperand();
            int parmCount = SignatureUtils.getNumParameters(signature);
            int reg = -1;
            XField field = null;
            MethodCall mc = null;
            String fieldSource = null;
            if (seen == Const.INVOKESTATIC) {
                XMethod xm = XFactory.createXMethod(getDottedClassConstantOperand(), methodName, signature, true);
                String genericSignature = xm.getSourceSignature();
                if ((genericSignature != null) && genericSignature.endsWith(">;")) {
                    return;
                }
            } else if (stack.getStackDepth() > parmCount) {
                OpcodeStack.Item obj = stack.getStackItem(parmCount);
                reg = obj.getRegisterNumber();
                field = obj.getXField();
                if (reg >= 0) {
                    mc = localMethodCalls.get(Integer.valueOf(reg));
                    MethodInfo mi = Statistics.getStatistics().getMethodStatistics(className, getNameConstantOperand(), signature);
                    if ((mi != null) && mi.getModifiesState()) {
                        clearFieldMethods(String.valueOf(reg));
                        return;
                    }
                } else if (field != null) {
                    fieldSource = (String) obj.getUserValue();
                    if (fieldSource == null) {
                        fieldSource = "";
                    }
                    mc = fieldMethodCalls.get(new FieldInfo(fieldSource, field.getName()));
                    MethodInfo mi = Statistics.getStatistics().getMethodStatistics(className, getNameConstantOperand(), signature);
                    if ((mi != null) && mi.getModifiesState()) {
                        clearFieldMethods(fieldSource);
                        return;
                    }
                }
            }
            int neededStackSize = parmCount + ((seen == Const.INVOKESTATIC) ? 0 : 1);
            if (stack.getStackDepth() >= neededStackSize) {
                Object[] parmConstants = new Object[parmCount];
                for (int i = 0; i < parmCount; i++) {
                    OpcodeStack.Item parm = stack.getStackItem(i);
                    parmConstants[i] = parm.getConstant();
                    if (parm.getSignature().startsWith(Values.SIG_ARRAY_PREFIX)) {
                        if (!Values.ZERO.equals(parm.getConstant())) {
                            return;
                        }
                        XField f = parm.getXField();
                        if (f != null) {
                            // Two different fields holding a 0 length array should be considered different
                            parmConstants[i] = f.getName() + ':' + parmConstants[i];
                        }
                    }
                    if (parmConstants[i] == null) {
                        return;
                    }
                }
                if (seen == Const.INVOKESTATIC) {
                    mc = staticMethodCalls.get(className);
                } else if ((reg < 0) && (field == null)) {
                    return;
                }
                if (mc != null) {
                    if (!signature.endsWith(Values.SIG_VOID) && methodName.equals(mc.getName()) && signature.equals(mc.getSignature()) && !isRiskyName(className, methodName) && !commonMethods.contains(new FQMethod(getClassConstantOperand(), methodName, signature))) {
                        Object[] parms = mc.getParms();
                        if (Arrays.equals(parms, parmConstants)) {
                            int ln = getLineNumber(pc);
                            if ((ln != mc.getLineNumber()) || (Math.abs(pc - mc.getPC()) < 10)) {
                                Statistics statistics = Statistics.getStatistics();
                                MethodInfo mi = statistics.getMethodStatistics(getClassConstantOperand(), methodName, signature);
                                bugReporter.reportBug(new BugInstance(this, BugType.PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS.name(), getBugPriority(methodName, mi)).addClass(this).addMethod(this).addSourceLine(this).addString(methodName + signature));
                            }
                        }
                    }
                    if (seen == Const.INVOKESTATIC) {
                        staticMethodCalls.remove(className);
                    } else {
                        if (reg >= 0) {
                            localMethodCalls.remove(Integer.valueOf(reg));
                        } else if (fieldSource != null) {
                            fieldMethodCalls.remove(new FieldInfo(fieldSource, field.getName()));
                        }
                    }
                } else {
                    int ln = getLineNumber(pc);
                    if (seen == Const.INVOKESTATIC) {
                        staticMethodCalls.put(className, new MethodCall(methodName, signature, parmConstants, pc, ln));
                    } else {
                        if (reg >= 0) {
                            localMethodCalls.put(Integer.valueOf(reg), new MethodCall(methodName, signature, parmConstants, pc, ln));
                        } else if (field != null) {
                            OpcodeStack.Item obj = stack.getStackItem(parmCount);
                            fieldSource = (String) obj.getUserValue();
                            if (fieldSource == null) {
                                fieldSource = "";
                            }
                            fieldMethodCalls.put(new FieldInfo(fieldSource, field.getName()), new MethodCall(methodName, signature, parmConstants, pc, ln));
                        }
                    }
                }
            }
        } else if (OpcodeUtils.isReturn(seen)) {
            localMethodCalls.clear();
            fieldMethodCalls.clear();
            branchTargets.clear(pc);
        }
    } finally {
        stack.sawOpcode(this, seen);
        if ((userValue != null) && (stack.getStackDepth() > 0)) {
            OpcodeStack.Item item = stack.getStackItem(0);
            item.setUserValue(userValue);
        }
    }
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) BugInstance(edu.umd.cs.findbugs.BugInstance) ToString(com.mebigfatguy.fbcontrib.utils.ToString) Statistics(com.mebigfatguy.fbcontrib.collect.Statistics) XField(edu.umd.cs.findbugs.ba.XField) XMethod(edu.umd.cs.findbugs.ba.XMethod) FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod) MethodInfo(com.mebigfatguy.fbcontrib.collect.MethodInfo)

Aggregations

XMethod (edu.umd.cs.findbugs.ba.XMethod)20 OpcodeStack (edu.umd.cs.findbugs.OpcodeStack)13 BugInstance (edu.umd.cs.findbugs.BugInstance)12 ToString (com.mebigfatguy.fbcontrib.utils.ToString)8 FQMethod (com.mebigfatguy.fbcontrib.utils.FQMethod)7 XField (edu.umd.cs.findbugs.ba.XField)5 JavaClass (org.apache.bcel.classfile.JavaClass)4 Nullable (javax.annotation.Nullable)3 QMethod (com.mebigfatguy.fbcontrib.utils.QMethod)2 Item (edu.umd.cs.findbugs.OpcodeStack.Item)2 XClass (edu.umd.cs.findbugs.ba.XClass)2 ClassDescriptor (edu.umd.cs.findbugs.classfile.ClassDescriptor)2 BitSet (java.util.BitSet)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 MethodInfo (com.mebigfatguy.fbcontrib.collect.MethodInfo)1 Statistics (com.mebigfatguy.fbcontrib.collect.Statistics)1 FieldDescriptor (edu.umd.cs.findbugs.classfile.FieldDescriptor)1 MethodDescriptor (edu.umd.cs.findbugs.classfile.MethodDescriptor)1 AnalysisPass (edu.umd.cs.findbugs.plan.AnalysisPass)1