Search in sources :

Example 6 with Item

use of edu.umd.cs.findbugs.OpcodeStack.Item in project fb-contrib by mebigfatguy.

the class LoggerOddities method checkForLoggerParam.

/**
 * looks for slf4j calls where an exception is passed as a logger parameter, expecting to be substituted for a {} marker. As slf4j just passes the exception
 * down to the message generation itself, the {} marker will go unpopulated.
 */
private void checkForLoggerParam() {
    if (Values.CONSTRUCTOR.equals(getNameConstantOperand())) {
        String cls = getClassConstantOperand();
        if ((cls.startsWith("java/") || cls.startsWith("javax/")) && cls.endsWith("Exception")) {
            String sig = getSigConstantOperand();
            List<String> types = SignatureUtils.getParameterSignatures(sig);
            if (types.size() <= stack.getStackDepth()) {
                for (int i = 0; i < types.size(); i++) {
                    String parmSig = types.get(i);
                    if (Values.SIG_JAVA_LANG_STRING.equals(parmSig)) {
                        OpcodeStack.Item item = stack.getStackItem(types.size() - i - 1);
                        String cons = (String) item.getConstant();
                        if ((cons != null) && cons.contains("{}")) {
                            bugReporter.reportBug(new BugInstance(this, BugType.LO_EXCEPTION_WITH_LOGGER_PARMS.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                            break;
                        }
                    }
                }
            }
        }
    }
}
Also used : Item(edu.umd.cs.findbugs.OpcodeStack.Item) OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) BugInstance(edu.umd.cs.findbugs.BugInstance) ToString(com.mebigfatguy.fbcontrib.utils.ToString)

Example 7 with Item

use of edu.umd.cs.findbugs.OpcodeStack.Item 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 8 with Item

use of edu.umd.cs.findbugs.OpcodeStack.Item in project fb-contrib by mebigfatguy.

the class LoggerOddities method getVarArgsParmCount.

/**
 * returns the number of parameters slf4j or log4j2 is expecting to inject into the format string
 *
 * @param signature
 *            the method signature of the error, warn, info, debug statement
 * @return the number of expected parameters
 */
@SuppressWarnings("unchecked")
private int getVarArgsParmCount(String signature) {
    if (SignatureBuilder.SIG_STRING_AND_OBJECT_TO_VOID.equals(signature)) {
        return 1;
    }
    if (SIG_STRING_AND_TWO_OBJECTS_TO_VOID.equals(signature)) {
        return 2;
    }
    OpcodeStack.Item item = stack.getStackItem(0);
    LOUserValue<Integer> uv = (LOUserValue<Integer>) item.getUserValue();
    if ((uv != null) && (uv.getType() == LOUserValue.LOType.ARRAY_SIZE)) {
        Integer size = uv.getValue();
        if (size != null) {
            return Math.abs(size.intValue());
        }
    }
    return -1;
}
Also used : Item(edu.umd.cs.findbugs.OpcodeStack.Item) OpcodeStack(edu.umd.cs.findbugs.OpcodeStack)

Aggregations

Item (edu.umd.cs.findbugs.OpcodeStack.Item)8 ToString (com.mebigfatguy.fbcontrib.utils.ToString)6 OpcodeStack (edu.umd.cs.findbugs.OpcodeStack)6 BugInstance (edu.umd.cs.findbugs.BugInstance)5 XMethod (edu.umd.cs.findbugs.ba.XMethod)2 JavaClass (org.apache.bcel.classfile.JavaClass)2 Matcher (java.util.regex.Matcher)1 Nullable (javax.annotation.Nullable)1 Constant (org.apache.bcel.classfile.Constant)1 ConstantClass (org.apache.bcel.classfile.ConstantClass)1 ConstantPool (org.apache.bcel.classfile.ConstantPool)1 LocalVariable (org.apache.bcel.classfile.LocalVariable)1