Search in sources :

Example 1 with ConstantInvokeDynamic

use of org.apache.bcel.classfile.ConstantInvokeDynamic in project fb-contrib by mebigfatguy.

the class OptionalIssues method sawOpcode.

/**
 * implements the visitor to look for reference compares of Optional, Optional use when more specific Optionals should be used, and use of orElse when
 * orElseGet would be more appropriate
 *
 * @param seen
 *            the opcode of the currently parsed instruction
 */
@Override
public void sawOpcode(int seen) {
    FQMethod curCalledMethod = null;
    Boolean sawPlainOptional = null;
    try {
        switch(seen) {
            case Const.IFNULL:
            case Const.IFNONNULL:
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    if ("Ljava/util/Optional;".equals(itm.getSignature())) {
                        bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_CHECKING_REFERENCE.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                    }
                }
                break;
            case Const.INVOKEDYNAMIC:
                // smells like a hack. Not sure how to do this better
                ConstantInvokeDynamic id = (ConstantInvokeDynamic) getConstantRefOperand();
                ConstantPool cp = getConstantPool();
                ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(id.getNameAndTypeIndex());
                ConstantUtf8 typeConstant = (ConstantUtf8) cp.getConstant(nameAndType.getSignatureIndex());
                curCalledMethod = new FQMethod(getClassName(), "lambda$" + id.getBootstrapMethodAttrIndex(), typeConstant.getBytes());
                break;
            case Const.INVOKESTATIC:
            case Const.INVOKEINTERFACE:
            case Const.INVOKESPECIAL:
                String clsName = getClassConstantOperand();
                String methodName = getNameConstantOperand();
                curCalledMethod = new FQMethod(clsName, methodName, getSigConstantOperand());
                if ("java/util/Optional".equals(clsName) && "of".equals(methodName)) {
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        String itmSig = itm.getSignature();
                        if (BOXED_OPTIONAL_TYPES.contains(itmSig)) {
                            bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_PRIMITIVE_VARIANT_PREFERRED.name(), LOW_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                        }
                    }
                }
                break;
            case Const.INVOKEVIRTUAL:
                curCalledMethod = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
                if (OR_ELSE_METHODS.contains(curCalledMethod)) {
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        if ((itm.getRegisterNumber() < 0) && (itm.getReturnValueOf() != null) && !isTrivialStackOps()) {
                            bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_USES_IMMEDIATE_EXECUTION.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                        }
                    }
                    if (OPTIONAL_OR_ELSE_METHOD.equals(curCalledMethod)) {
                        sawPlainOptional = Boolean.TRUE;
                    }
                } else if (OR_ELSE_GET_METHODS.contains(curCalledMethod)) {
                    if (!activeStackOps.isEmpty()) {
                        ActiveStackOp op = activeStackOps.getLast();
                        FQMethod method = op.getMethod();
                        if (method == null) {
                            bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_USES_ORELSEGET_WITH_NULL.name(), LOW_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                        } else {
                            Method getMethod = getLambdaMethod(method.getMethodName());
                            if (getMethod != null) {
                                byte[] byteCode = getMethod.getCode().getCode();
                                if (byteCode.length <= 4) {
                                    // we are looking for ALOAD, GETFIELD, or LDC followed by ARETURN, that should fit in 4 bytes
                                    if (!hasInvoke(byteCode)) {
                                        bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_USES_DELAYED_EXECUTION.name(), LOW_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
                                    }
                                }
                            }
                        }
                    }
                    if (OPTIONAL_OR_ELSE_GET_METHOD.equals(curCalledMethod)) {
                        sawPlainOptional = Boolean.TRUE;
                    }
                } else if (OPTIONAL_GET_METHOD.equals(curCalledMethod)) {
                    sawPlainOptional = Boolean.TRUE;
                }
                break;
        }
    } finally {
        stack.sawOpcode(this, seen);
        int stackDepth = stack.getStackDepth();
        if (stackDepth == 0) {
            activeStackOps.clear();
        } else {
            activeStackOps.addLast(new ActiveStackOp(seen, curCalledMethod));
            while (activeStackOps.size() > stackDepth) {
                activeStackOps.removeFirst();
            }
            if (sawPlainOptional != null) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                itm.setUserValue(sawPlainOptional);
            }
        }
    }
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) BugInstance(edu.umd.cs.findbugs.BugInstance) ToString(com.mebigfatguy.fbcontrib.utils.ToString) Method(org.apache.bcel.classfile.Method) FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod) ConstantUtf8(org.apache.bcel.classfile.ConstantUtf8) ConstantNameAndType(org.apache.bcel.classfile.ConstantNameAndType) ConstantPool(org.apache.bcel.classfile.ConstantPool) FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod) ConstantInvokeDynamic(org.apache.bcel.classfile.ConstantInvokeDynamic)

Example 2 with ConstantInvokeDynamic

use of org.apache.bcel.classfile.ConstantInvokeDynamic in project fb-contrib by mebigfatguy.

the class FunctionalInterfaceIssues method sawOpcode.

@Override
public void sawOpcode(int seen) {
    try {
        switch(seen) {
            case Const.INVOKEDYNAMIC:
                List<FIInfo> fiis = functionalInterfaceInfo.get(getMethod());
                if (fiis == null) {
                    fiis = new ArrayList<>();
                    functionalInterfaceInfo.put(getMethod(), fiis);
                }
                ConstantInvokeDynamic cid = (ConstantInvokeDynamic) getConstantRefOperand();
                ConstantMethodHandle cmh = getMethodHandle(cid.getBootstrapMethodAttrIndex());
                FIInfo fii = new FIInfo(getPC(), cid.getBootstrapMethodAttrIndex());
                fiis.add(fii);
                break;
        }
    } finally {
        stack.sawOpcode(this, seen);
    }
}
Also used : ConstantInvokeDynamic(org.apache.bcel.classfile.ConstantInvokeDynamic) ConstantMethodHandle(org.apache.bcel.classfile.ConstantMethodHandle)

Example 3 with ConstantInvokeDynamic

use of org.apache.bcel.classfile.ConstantInvokeDynamic in project fb-contrib by mebigfatguy.

the class OverlyPermissiveMethod method sawOpcode.

@Override
public void sawOpcode(int seen) {
    try {
        stack.precomputation(this);
        switch(seen) {
            case Const.INVOKEVIRTUAL:
            case Const.INVOKEINTERFACE:
            case Const.INVOKESTATIC:
            case Const.INVOKESPECIAL:
                {
                    String calledClass = getClassConstantOperand();
                    String sig = getSigConstantOperand();
                    MethodInfo mi = Statistics.getStatistics().getMethodStatistics(calledClass, getNameConstantOperand(), sig);
                    if (mi != null) {
                        if (seen == Const.INVOKEINTERFACE) {
                            mi.addCallingAccess(Const.ACC_PUBLIC);
                        } else {
                            String calledPackage;
                            int slashPos = calledClass.lastIndexOf('/');
                            if (slashPos >= 0) {
                                calledPackage = calledClass.substring(0, slashPos);
                            } else {
                                calledPackage = "";
                            }
                            boolean sameClass = calledClass.equals(callingClass);
                            boolean samePackage = calledPackage.equals(callingPackage);
                            if (sameClass) {
                                mi.addCallingAccess(Const.ACC_PRIVATE);
                            } else if (samePackage) {
                                mi.addCallingAccess(0);
                            } else {
                                if (seen == Const.INVOKESTATIC) {
                                    mi.addCallingAccess(Const.ACC_PUBLIC);
                                } else if (isCallingOnThis(sig)) {
                                    mi.addCallingAccess(Const.ACC_PROTECTED);
                                } else {
                                    mi.addCallingAccess(Const.ACC_PUBLIC);
                                }
                            }
                        }
                    }
                }
                break;
            case Const.INVOKEDYNAMIC:
                ConstantInvokeDynamic id = (ConstantInvokeDynamic) getConstantRefOperand();
                BootstrapMethod bm = getBootstrapMethod(id.getBootstrapMethodAttrIndex());
                if (bm != null) {
                    ConstantPool pool = getConstantPool();
                    ConstantMethodHandle mh = getFirstMethodHandle(pool, bm);
                    if (mh != null) {
                        ConstantCP ref = (ConstantCP) pool.getConstant(mh.getReferenceIndex());
                        ConstantClass cc = (ConstantClass) pool.getConstant(ref.getClassIndex());
                        String clz = ((ConstantUtf8) pool.getConstant(cc.getNameIndex())).getBytes();
                        ConstantNameAndType nameAndType = (ConstantNameAndType) pool.getConstant(ref.getNameAndTypeIndex());
                        String sig = ((ConstantUtf8) pool.getConstant(nameAndType.getSignatureIndex())).getBytes();
                        String name = ((ConstantUtf8) pool.getConstant(nameAndType.getNameIndex())).getBytes();
                        MethodInfo mi = Statistics.getStatistics().getMethodStatistics(clz, name, sig);
                        mi.addCallingAccess(Const.ACC_PUBLIC);
                    }
                }
                break;
            default:
                break;
        }
    } finally {
        stack.sawOpcode(this, seen);
    }
}
Also used : BootstrapMethod(org.apache.bcel.classfile.BootstrapMethod) ConstantPool(org.apache.bcel.classfile.ConstantPool) ConstantInvokeDynamic(org.apache.bcel.classfile.ConstantInvokeDynamic) MethodInfo(com.mebigfatguy.fbcontrib.collect.MethodInfo) ConstantMethodHandle(org.apache.bcel.classfile.ConstantMethodHandle) ConstantUtf8(org.apache.bcel.classfile.ConstantUtf8) ConstantCP(org.apache.bcel.classfile.ConstantCP) ConstantClass(org.apache.bcel.classfile.ConstantClass) ConstantNameAndType(org.apache.bcel.classfile.ConstantNameAndType)

Aggregations

ConstantInvokeDynamic (org.apache.bcel.classfile.ConstantInvokeDynamic)3 ConstantMethodHandle (org.apache.bcel.classfile.ConstantMethodHandle)2 ConstantNameAndType (org.apache.bcel.classfile.ConstantNameAndType)2 ConstantPool (org.apache.bcel.classfile.ConstantPool)2 ConstantUtf8 (org.apache.bcel.classfile.ConstantUtf8)2 MethodInfo (com.mebigfatguy.fbcontrib.collect.MethodInfo)1 FQMethod (com.mebigfatguy.fbcontrib.utils.FQMethod)1 ToString (com.mebigfatguy.fbcontrib.utils.ToString)1 BugInstance (edu.umd.cs.findbugs.BugInstance)1 OpcodeStack (edu.umd.cs.findbugs.OpcodeStack)1 BootstrapMethod (org.apache.bcel.classfile.BootstrapMethod)1 ConstantCP (org.apache.bcel.classfile.ConstantCP)1 ConstantClass (org.apache.bcel.classfile.ConstantClass)1 Method (org.apache.bcel.classfile.Method)1