Search in sources :

Example 21 with FQMethod

use of com.mebigfatguy.fbcontrib.utils.FQMethod 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)

Example 22 with FQMethod

use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.

the class JPAIssues method processInvoke.

@Nullable
private JPAUserValue processInvoke() {
    String dottedCls = getDottedClassConstantOperand();
    String methodName = getNameConstantOperand();
    String signature = getSigConstantOperand();
    TransactionalType calledMethodTransType = getTransactionalType(new FQMethod(dottedCls, methodName, signature));
    if ((calledMethodTransType != TransactionalType.NONE) && !TransactionalType.isContainedBy(calledMethodTransType, methodTransType)) {
        int numParameters = SignatureUtils.getNumParameters(signature);
        if (stack.getStackDepth() > numParameters) {
            OpcodeStack.Item itm = stack.getStackItem(numParameters);
            if (itm.getRegisterNumber() == 0) {
                bugReporter.reportBug(new BugInstance(this, BugType.JPAI_NON_PROXIED_TRANSACTION_CALL.name(), isPublic ? NORMAL_PRIORITY : LOW_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
            }
        }
    }
    if ("javax.persistence.EntityManager".equals(dottedCls) && "merge".equals(methodName)) {
        return JPAUserValue.MERGE;
    }
    return null;
}
Also used : OpcodeStack(edu.umd.cs.findbugs.OpcodeStack) FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod) BugInstance(edu.umd.cs.findbugs.BugInstance) Nullable(javax.annotation.Nullable)

Example 23 with FQMethod

use of com.mebigfatguy.fbcontrib.utils.FQMethod 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 24 with FQMethod

use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.

the class Statistics method addImmutabilityStatus.

public void addImmutabilityStatus(String className, String methodName, String signature, ImmutabilityType imType) {
    FQMethod key = new FQMethod(className, methodName, signature);
    MethodInfo mi = methodStatistics.get(key);
    if (mi == null) {
        mi = new MethodInfo();
        methodStatistics.put(key, mi);
    }
    mi.setImmutabilityType(imType);
}
Also used : FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod)

Example 25 with FQMethod

use of com.mebigfatguy.fbcontrib.utils.FQMethod in project fb-contrib by mebigfatguy.

the class Statistics method addMethodStatistics.

public MethodInfo addMethodStatistics(String className, String methodName, String signature, int access, int numBytes, int numMethodCalls) {
    FQMethod key = new FQMethod(className, methodName, signature);
    MethodInfo mi = methodStatistics.get(key);
    if (mi == null) {
        mi = new MethodInfo();
        methodStatistics.put(key, mi);
    }
    mi.setNumBytes(numBytes);
    mi.setNumMethodCalls(numMethodCalls);
    mi.setDeclaredAccess(access);
    return mi;
}
Also used : FQMethod(com.mebigfatguy.fbcontrib.utils.FQMethod)

Aggregations

FQMethod (com.mebigfatguy.fbcontrib.utils.FQMethod)25 OpcodeStack (edu.umd.cs.findbugs.OpcodeStack)15 BugInstance (edu.umd.cs.findbugs.BugInstance)13 XMethod (edu.umd.cs.findbugs.ba.XMethod)7 ToString (com.mebigfatguy.fbcontrib.utils.ToString)6 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Method (org.apache.bcel.classfile.Method)3 MethodInfo (com.mebigfatguy.fbcontrib.collect.MethodInfo)2 QMethod (com.mebigfatguy.fbcontrib.utils.QMethod)2 JavaClass (org.apache.bcel.classfile.JavaClass)2 Statistics (com.mebigfatguy.fbcontrib.collect.Statistics)1 XField (edu.umd.cs.findbugs.ba.XField)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 Nullable (javax.annotation.Nullable)1 AnnotationEntry (org.apache.bcel.classfile.AnnotationEntry)1 BootstrapMethod (org.apache.bcel.classfile.BootstrapMethod)1