Search in sources :

Example 16 with XMethod

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

the class ListIndexedIterating method sawOpcodeBug.

/**
 * the second pass to look for get methods on the for loop reg
 *
 * @param seen
 *            the currently parsed opcode
 */
private void sawOpcodeBug(final int seen) {
    try {
        stack.precomputation(this);
        Iterator<ForLoop> it = possibleForLoops.iterator();
        while (it.hasNext()) {
            ForLoop fl = it.next();
            switch(fl.getLoopState()) {
                case LOOP_NOT_STARTED:
                    if (getPC() == fl.getLoopStart()) {
                        if (OpcodeUtils.isILoad(seen) && (RegisterUtils.getLoadReg(this, seen) == fl.getLoopReg())) {
                            fl.setLoopState(LoopState.LOOP_INDEX_LOADED_FOR_TEST);
                            continue;
                        }
                        it.remove();
                    }
                    break;
                case LOOP_INDEX_LOADED_FOR_TEST:
                    if (getPC() >= fl.getLoopEnd()) {
                        it.remove();
                        continue;
                    }
                    if (seen == Const.IF_ICMPGE) {
                        if (stack.getStackDepth() > 1) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            if (itm.getConstant() != null) {
                                it.remove();
                                continue;
                            }
                            XMethod constantSource = itm.getReturnValueOf();
                            if (constantSource != null) {
                                if (!"size".equals(constantSource.getMethodDescriptor().getName())) {
                                    it.remove();
                                    continue;
                                }
                            } else if (getPrevOpcode(1) != Const.ARRAYLENGTH) {
                                it.remove();
                                continue;
                            }
                        }
                        int branchTarget = getBranchTarget();
                        if ((branchTarget >= (fl.getLoopEnd() + 3)) && (branchTarget <= (fl.getLoopEnd() + 5))) {
                            fl.setLoopState(LoopState.LOOP_IN_BODY);
                            continue;
                        }
                    }
                    break;
                case LOOP_IN_BODY:
                case LOOP_IN_BODY_WITH_GET:
                    if ((getPC() == fl.getLoopEnd()) && (fl.getLoopState() == LoopState.LOOP_IN_BODY_WITH_GET)) {
                        bugReporter.reportBug(new BugInstance(this, "LII_LIST_INDEXED_ITERATING", NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLineRange(this, fl.getLoopStart(), fl.getLoopEnd()));
                        it.remove();
                    }
                    if (getPC() > fl.getLoopEnd()) {
                        it.remove();
                    }
                    if (OpcodeUtils.isILoad(seen)) {
                        loopReg = RegisterUtils.getLoadReg(this, seen);
                        if (loopReg == fl.getLoopReg()) {
                            fl.setLoopRegLoaded(true);
                        }
                    } else if (fl.getLoopRegLoaded()) {
                        boolean sawGet = ((seen == Const.INVOKEINTERFACE) && Values.SLASHED_JAVA_UTIL_LIST.equals(getClassConstantOperand()) && "get".equals(getNameConstantOperand()) && SignatureBuilder.SIG_INT_TO_OBJECT.equals(getSigConstantOperand()));
                        if (!sawGet) {
                            it.remove();
                        } else {
                            fl.setLoopState(LoopState.LOOP_IN_BODY_WITH_GET);
                            if (stack.getStackDepth() > 1) {
                                OpcodeStack.Item itm = stack.getStackItem(0);
                                if (!itm.couldBeZero()) {
                                    it.remove();
                                } else {
                                    itm = stack.getStackItem(1);
                                    if (fl.isSecondItem(itm)) {
                                        it.remove();
                                    }
                                }
                            }
                            fl.setLoopRegLoaded(false);
                        }
                    }
                    break;
            }
        }
    } finally {
        stack.sawOpcode(this, seen);
    }
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) XMethod(edu.umd.cs.findbugs.ba.XMethod) BugInstance(edu.umd.cs.findbugs.BugInstance)

Example 17 with XMethod

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

the class LiteralStringComparison method sawOpcode.

/**
 * looks for strings comparisons where the stack object is a literal
 *
 * @param seen
 *            the currently parsed opcode
 */
@Override
public void sawOpcode(final int seen) {
    Object hashCodedStringRef = null;
    try {
        stack.precomputation(this);
        switch(seen) {
            case INVOKEVIRTUAL:
                if (Values.SLASHED_JAVA_LANG_STRING.equals(getClassConstantOperand())) {
                    String calledMethodName = getNameConstantOperand();
                    String calledMethodSig = getSigConstantOperand();
                    if (("equals".equals(calledMethodName) && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(calledMethodSig)) || ("compareTo".equals(calledMethodName) && SignatureBuilder.SIG_STRING_TO_INT.equals(calledMethodSig)) || ("equalsIgnoreCase".equals(calledMethodName) && SignatureBuilder.SIG_STRING_TO_BOOLEAN.equals(calledMethodSig))) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            Object constant = itm.getConstant();
                            if ((constant != null) && constant.getClass().equals(String.class) && !lookupSwitchOnString()) {
                                bugReporter.reportBug(// very
                                new BugInstance(this, "LSC_LITERAL_STRING_COMPARISON", HIGH_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                            }
                        }
                    } else if (Values.HASHCODE.equals(calledMethodName) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        int reg = item.getRegisterNumber();
                        if (reg >= 0) {
                            hashCodedStringRef = String.valueOf(reg);
                        } else {
                            XField xf = item.getXField();
                            if (xf != null) {
                                hashCodedStringRef = xf.getName();
                            } else {
                                XMethod xm = item.getReturnValueOf();
                                if (xm != null) {
                                    hashCodedStringRef = xm.toString();
                                }
                            }
                        }
                    }
                }
                break;
            case LOOKUPSWITCH:
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    String stringRef = (String) item.getUserValue();
                    if (stringRef != null) {
                        int[] offsets = getSwitchOffsets();
                        BitSet bs = new BitSet();
                        int pc = getPC();
                        for (int offset : offsets) {
                            bs.set(pc + offset);
                        }
                        bs.set(pc + getDefaultSwitchOffset());
                        lookupSwitches.add(new LookupDetails(stringRef, bs));
                    }
                }
                break;
            default:
                break;
        }
    } finally {
        stack.sawOpcode(this, seen);
        if ((hashCodedStringRef != null) && (stack.getStackDepth() > 0)) {
            OpcodeStack.Item item = stack.getStackItem(0);
            item.setUserValue(hashCodedStringRef);
        }
        if (!lookupSwitches.isEmpty()) {
            int innerMostSwitch = lookupSwitches.size() - 1;
            LookupDetails details = lookupSwitches.get(innerMostSwitch);
            if (details.switchTargets.get(getPC()) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(details.getStringReference());
            }
            // runs on 1.7
            if (getPC() >= details.getSwitchTargets().previousSetBit(Integer.MAX_VALUE)) {
                lookupSwitches.remove(innerMostSwitch);
            }
        }
    }
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) XField(edu.umd.cs.findbugs.ba.XField) XMethod(edu.umd.cs.findbugs.ba.XMethod) BitSet(java.util.BitSet) BugInstance(edu.umd.cs.findbugs.BugInstance) ToString(com.mebigfatguy.fbcontrib.utils.ToString)

Example 18 with XMethod

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

the class ConstantListIndex method isArrayFromUbiquitousMethod.

/**
 * returns whether the array item was returned from a common method that the user can't do anything about and so don't report CLI in this case.
 *
 * @param item
 *            the stack item representing the array
 * @return if the array was returned from a common method
 */
private static boolean isArrayFromUbiquitousMethod(OpcodeStack.Item item) {
    XMethod method = item.getReturnValueOf();
    if (method == null) {
        return false;
    }
    FQMethod methodDesc = new FQMethod(method.getClassName().replace('.', '/'), method.getName(), method.getSignature());
    return ubiquitousMethods.contains(methodDesc);
}
Also used : XMethod(edu.umd.cs.findbugs.ba.XMethod) FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod)

Example 19 with XMethod

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

the class LoggerOddities method sawOpcode.

/**
 * implements the visitor to look for calls to Logger.getLogger with the wrong class name
 *
 * @param seen
 *            the opcode of the currently parsed instruction
 */
@Override
@SuppressWarnings("unchecked")
public void sawOpcode(int seen) {
    String ldcClassName = null;
    String seenMethodName = null;
    boolean seenToString = false;
    boolean seenFormatterLogger = false;
    int exMessageReg = -1;
    Integer arraySize = null;
    boolean simpleFormat = false;
    try {
        stack.precomputation(this);
        if ((seen == Const.LDC) || (seen == Const.LDC_W)) {
            Constant c = getConstantRefOperand();
            if (c instanceof ConstantClass) {
                ConstantPool pool = getConstantPool();
                ldcClassName = ((ConstantUtf8) pool.getConstant(((ConstantClass) c).getNameIndex())).getBytes();
            }
        } else if (seen == Const.INVOKESTATIC) {
            lookForSuspectClasses();
            String clsName = getClassConstantOperand();
            String methodName = getNameConstantOperand();
            if (Values.SLASHED_JAVA_LANG_STRING.equals(clsName) && "format".equals(methodName) && (stack.getStackDepth() >= 2)) {
                String format = (String) stack.getStackItem(1).getConstant();
                if (format != null) {
                    Matcher m = NON_SIMPLE_FORMAT.matcher(format);
                    if (!m.matches()) {
                        simpleFormat = true;
                    }
                }
            } else if ("getFormatterLogger".equals(methodName) && LOG4J2_LOGMANAGER.equals(clsName)) {
                seenFormatterLogger = true;
            }
        } else if (((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) && (throwableClass != null)) {
            String mthName = getNameConstantOperand();
            if ("getName".equals(mthName)) {
                if (stack.getStackDepth() >= 1) {
                    // Foo.class.getName() is being called, so we pass the
                    // name of the class to the current top of the stack
                    // (the name of the class is currently on the top of the
                    // stack, but won't be on the stack at all next opcode)
                    Item stackItem = stack.getStackItem(0);
                    LOUserValue<String> uv = (LOUserValue<String>) stackItem.getUserValue();
                    if ((uv != null) && (uv.getType() == LOUserValue.LOType.CLASS_NAME)) {
                        ldcClassName = uv.getValue();
                    }
                }
            } else if ("getMessage".equals(mthName)) {
                String callingClsName = getClassConstantOperand();
                JavaClass cls = Repository.lookupClass(callingClsName);
                if (cls.instanceOf(throwableClass) && (stack.getStackDepth() > 0)) {
                    OpcodeStack.Item exItem = stack.getStackItem(0);
                    exMessageReg = exItem.getRegisterNumber();
                }
            } else if (LOGGER_METHODS.contains(mthName)) {
                checkForProblemsWithLoggerMethods();
            } else if (Values.TOSTRING.equals(mthName) && SignatureBuilder.SIG_VOID_TO_STRING.equals(getSigConstantOperand())) {
                String callingClsName = getClassConstantOperand();
                if (SignatureUtils.isPlainStringConvertableClass(callingClsName) && (stack.getStackDepth() > 0)) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    // if the stringbuilder was previously stored, don't report it
                    if (item.getRegisterNumber() < 0) {
                        seenMethodName = mthName;
                    }
                }
                if (seenMethodName == null) {
                    seenToString = true;
                }
            }
        } else if (seen == Const.INVOKESPECIAL) {
            checkForLoggerParam();
        } else if (seen == Const.ANEWARRAY) {
            if (stack.getStackDepth() > 0) {
                OpcodeStack.Item sizeItem = stack.getStackItem(0);
                Object con = sizeItem.getConstant();
                if (con instanceof Integer) {
                    arraySize = (Integer) con;
                }
            }
        } else if (seen == Const.AASTORE) {
            if (stack.getStackDepth() >= 3) {
                OpcodeStack.Item arrayItem = stack.getStackItem(2);
                LOUserValue<Integer> uv = (LOUserValue<Integer>) arrayItem.getUserValue();
                if ((uv != null) && (uv.getType() == LOUserValue.LOType.ARRAY_SIZE)) {
                    Integer size = uv.getValue();
                    if ((size != null) && (size.intValue() > 0) && hasExceptionOnStack()) {
                        arrayItem.setUserValue(new LOUserValue<>(LOUserValue.LOType.ARRAY_SIZE, Integer.valueOf(-size.intValue())));
                    }
                }
            }
        } else if (seen == PUTSTATIC) {
            OpcodeStack.Item itm = stack.getStackItem(0);
            if (isStaticInitializer && isNonPrivateLogField(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand())) {
                XMethod m = itm.getReturnValueOf();
                if ((m != null) && isLoggerWithClassParm(m)) {
                    bugReporter.reportBug(new BugInstance(this, BugType.LO_NON_PRIVATE_STATIC_LOGGER.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                }
            }
            LOUserValue<Void> loggerUV = (LOUserValue<Void>) itm.getUserValue();
            if ((loggerUV != null) && (loggerUV.getType() == LOUserValue.LOType.FORMATTER_LOGGER)) {
                formatterLoggers.add(getNameConstantOperand());
            }
        } else if (seen == GETSTATIC) {
            if (formatterLoggers.contains(getNameConstantOperand())) {
                seenFormatterLogger = true;
            }
        } else if (OpcodeUtils.isAStore(seen) && (stack.getStackDepth() > 0)) {
            OpcodeStack.Item item = stack.getStackItem(0);
            LOUserValue<String> uv = (LOUserValue<String>) item.getUserValue();
            if (uv != null) {
                if (((uv.getType() == LOUserValue.LOType.METHOD_NAME) && Values.TOSTRING.equals(uv.getValue())) || (uv.getType() == LOUserValue.LOType.SIMPLE_FORMAT) || (uv.getType() == LOUserValue.LOType.TOSTRING)) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.NULL, null));
                }
            }
        }
    } catch (ClassNotFoundException cnfe) {
        bugReporter.reportMissingClass(cnfe);
    } finally {
        TernaryPatcher.pre(stack, seen);
        stack.sawOpcode(this, seen);
        TernaryPatcher.post(stack, seen);
        if (stack.getStackDepth() > 0) {
            OpcodeStack.Item item = stack.getStackItem(0);
            if (ldcClassName != null) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.CLASS_NAME, ldcClassName));
            } else if (seenMethodName != null) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.METHOD_NAME, seenMethodName));
            } else if (exMessageReg >= 0) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.MESSAGE_REG, Integer.valueOf(exMessageReg)));
            } else if (arraySize != null) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.ARRAY_SIZE, arraySize));
            } else if (simpleFormat) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.SIMPLE_FORMAT, Boolean.TRUE));
            } else if (seenToString) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.TOSTRING, null));
            } else if (seenFormatterLogger) {
                item.setUserValue(new LOUserValue<>(LOUserValue.LOType.FORMATTER_LOGGER, null));
            }
        }
    }
}
Also used : Item(edu.umd.cs.findbugs.OpcodeStack.Item) OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) Matcher(java.util.regex.Matcher) Constant(org.apache.bcel.classfile.Constant) BugInstance(edu.umd.cs.findbugs.BugInstance) ToString(com.mebigfatguy.fbcontrib.utils.ToString) Item(edu.umd.cs.findbugs.OpcodeStack.Item) JavaClass(org.apache.bcel.classfile.JavaClass) ConstantPool(org.apache.bcel.classfile.ConstantPool) XMethod(edu.umd.cs.findbugs.ba.XMethod) ConstantClass(org.apache.bcel.classfile.ConstantClass)

Example 20 with XMethod

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

the class InappropriateToStringUse method processInvokeVirtual.

@Nullable
private String processInvokeVirtual() throws ClassNotFoundException {
    String methodName = getNameConstantOperand();
    if (Values.TOSTRING.equals(methodName)) {
        String signature = getSigConstantOperand();
        if (SignatureBuilder.SIG_VOID_TO_STRING.equals(signature)) {
            String className = getClassConstantOperand();
            if (!validToStringClasses.contains(className) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                JavaClass cls = item.getJavaClass();
                if (cls != null) {
                    return cls.getPackageName();
                }
            }
        }
    } else if (stringAlgoMethods.contains(methodName)) {
        String className = getClassConstantOperand();
        if (Values.SLASHED_JAVA_LANG_STRING.equals(className)) {
            String signature = getSigConstantOperand();
            int numParms = SignatureUtils.getNumParameters(signature);
            if (stack.getStackDepth() > numParms) {
                OpcodeStack.Item item = stack.getStackItem(numParms);
                if (item.getUserValue() != null) {
                    XMethod xm = item.getReturnValueOf();
                    String tsPackage = null;
                    if (xm != null) {
                        tsPackage = xm.getPackageName();
                    }
                    if ((tsPackage == null) || !SignatureUtils.similarPackages(tsPackage, packageName, 2)) {
                        bugReporter.reportBug(new BugInstance(this, BugType.ITU_INAPPROPRIATE_TOSTRING_USE.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                    }
                }
            }
        }
    }
    return null;
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) JavaClass(org.apache.bcel.classfile.JavaClass) XMethod(edu.umd.cs.findbugs.ba.XMethod) BugInstance(edu.umd.cs.findbugs.BugInstance) Nullable(javax.annotation.Nullable)

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