📄 findbadcast2.java
字号:
package edu.umd.cs.findbugs.detect;import java.util.BitSet;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import org.apache.bcel.Constants;import org.apache.bcel.Repository;import org.apache.bcel.classfile.Attribute;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.LineNumberTable;import org.apache.bcel.classfile.Method;import org.apache.bcel.classfile.Synthetic;import org.apache.bcel.generic.CHECKCAST;import org.apache.bcel.generic.ConstantPoolGen;import org.apache.bcel.generic.INSTANCEOF;import org.apache.bcel.generic.Instruction;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.InvokeInstruction;import org.apache.bcel.generic.MethodGen;import org.apache.bcel.generic.ObjectType;import org.apache.bcel.generic.ReferenceType;import org.apache.bcel.generic.Type;import org.apache.bcel.generic.TypedInstruction;import edu.umd.cs.findbugs.BugAnnotation;import edu.umd.cs.findbugs.DeepSubtypeAnalysis;import edu.umd.cs.findbugs.BugAccumulator;import edu.umd.cs.findbugs.BugInstance;import edu.umd.cs.findbugs.BugReporter;import edu.umd.cs.findbugs.Detector;import edu.umd.cs.findbugs.FieldAnnotation;import edu.umd.cs.findbugs.LocalVariableAnnotation;import edu.umd.cs.findbugs.SourceLineAnnotation;import edu.umd.cs.findbugs.SystemProperties;import edu.umd.cs.findbugs.TypeAnnotation;import edu.umd.cs.findbugs.ba.AnalysisContext;import edu.umd.cs.findbugs.ba.CFG;import edu.umd.cs.findbugs.ba.CFGBuilderException;import edu.umd.cs.findbugs.ba.ClassContext;import edu.umd.cs.findbugs.ba.DataflowAnalysisException;import edu.umd.cs.findbugs.ba.Location;import edu.umd.cs.findbugs.ba.MethodUnprofitableException;import edu.umd.cs.findbugs.ba.npe.IsNullValue;import edu.umd.cs.findbugs.ba.npe.IsNullValueDataflow;import edu.umd.cs.findbugs.ba.npe.IsNullValueFrame;import edu.umd.cs.findbugs.ba.npe.NullDerefAndRedundantComparisonFinder;import edu.umd.cs.findbugs.ba.type.NullType;import edu.umd.cs.findbugs.ba.type.TopType;import edu.umd.cs.findbugs.ba.type.TypeDataflow;import edu.umd.cs.findbugs.ba.type.TypeFrame;import edu.umd.cs.findbugs.ba.vna.ValueNumber;import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;public class FindBadCast2 implements Detector { private BugReporter bugReporter; private Set<String> concreteCollectionClasses = new HashSet<String>(); private Set<String> abstractCollectionClasses = new HashSet<String>(); private Set<String> veryAbstractCollectionClasses = new HashSet<String>(); private static final boolean DEBUG = SystemProperties.getBoolean("bc.debug"); public FindBadCast2(BugReporter bugReporter) { this.bugReporter = bugReporter; veryAbstractCollectionClasses.add("java.util.Collection"); veryAbstractCollectionClasses.add("java.util.Iterable"); abstractCollectionClasses.add("java.util.Collection"); abstractCollectionClasses.add("java.util.List"); abstractCollectionClasses.add("java.util.Set"); abstractCollectionClasses.add("java.util.SortedSet"); abstractCollectionClasses.add("java.util.SortedMap"); abstractCollectionClasses.add("java.util.Map"); concreteCollectionClasses.add("java.util.LinkedHashMap"); concreteCollectionClasses.add("java.util.LinkedHashSet"); concreteCollectionClasses.add("java.util.HashMap"); concreteCollectionClasses.add("java.util.HashSet"); concreteCollectionClasses.add("java.util.TreeMap"); concreteCollectionClasses.add("java.util.TreeSet"); concreteCollectionClasses.add("java.util.ArrayList"); concreteCollectionClasses.add("java.util.LinkedList"); concreteCollectionClasses.add("java.util.Hashtable"); concreteCollectionClasses.add("java.util.Vector"); } public void visitClassContext(ClassContext classContext) { JavaClass javaClass = classContext.getJavaClass(); Method[] methodList = javaClass.getMethods(); for (Method method : methodList) { if (method.getCode() == null) continue; try { analyzeMethod(classContext, method); } catch (MethodUnprofitableException e) { assert true; // move along; nothing to see } catch (CFGBuilderException e) { String msg = "Detector " + this.getClass().getName() + " caught exception while analyzing " + javaClass.getClassName() + "." + method.getName() + " : " + method.getSignature(); bugReporter.logError(msg , e); } catch (DataflowAnalysisException e) { String msg = "Detector " + this.getClass().getName() + " caught exception while analyzing " + javaClass.getClassName() + "." + method.getName() + " : " + method.getSignature(); bugReporter.logError(msg, e); } } } public boolean prescreen(ClassContext classContext, Method method) { BitSet bytecodeSet = classContext.getBytecodeSet(method); return bytecodeSet != null && (bytecodeSet.get(Constants.CHECKCAST) || bytecodeSet.get(Constants.INSTANCEOF)); } private boolean isSynthetic(Method m) { Attribute[] attrs = m.getAttributes(); for (Attribute attr : attrs) { if (attr instanceof Synthetic) return true; } return false; } private Set<ValueNumber> getParameterValueNumbers(ClassContext classContext, Method method, CFG cfg ) throws DataflowAnalysisException, CFGBuilderException { ValueNumberDataflow vnaDataflow = classContext.getValueNumberDataflow(method); ValueNumberFrame vnaFrameAtEntry = vnaDataflow.getStartFact(cfg .getEntry()); Set<ValueNumber> paramValueNumberSet = new HashSet<ValueNumber>(); int firstParam = method.isStatic() ? 0 : 1; for (int i = firstParam; i < vnaFrameAtEntry.getNumLocals(); ++i) { paramValueNumberSet.add(vnaFrameAtEntry.getValue(i)); } return paramValueNumberSet; } private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { if (isSynthetic(method) || !prescreen(classContext, method)) return; BugAccumulator accumulator = new BugAccumulator(bugReporter); CFG cfg = classContext.getCFG(method); TypeDataflow typeDataflow = classContext.getTypeDataflow(method); IsNullValueDataflow isNullDataflow = classContext.getIsNullValueDataflow(method); Set<ValueNumber> paramValueNumberSet = null; ValueNumberDataflow vnaDataflow = null; ConstantPoolGen cpg = classContext.getConstantPoolGen(); MethodGen methodGen = classContext.getMethodGen(method); if (methodGen == null) return; String methodName = methodGen.getClassName() + "." + methodGen.getName(); String sourceFile = classContext.getJavaClass().getSourceFileName(); if (DEBUG) { System.out.println("Checking " + methodName); } Set<SourceLineAnnotation> haveInstanceOf = new HashSet<SourceLineAnnotation>(); Set<SourceLineAnnotation> haveCast = new HashSet<SourceLineAnnotation>(); Set<SourceLineAnnotation> haveMultipleInstanceOf = new HashSet<SourceLineAnnotation>(); Set<SourceLineAnnotation> haveMultipleCast = new HashSet<SourceLineAnnotation>(); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); InstructionHandle handle = location.getHandle(); Instruction ins = handle.getInstruction(); if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF)) continue; SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation .fromVisitedInstruction(classContext, methodGen, sourceFile, handle); if (ins instanceof CHECKCAST) { if (!haveCast.add(sourceLineAnnotation)) haveMultipleCast.add(sourceLineAnnotation); } else { if (!haveInstanceOf.add(sourceLineAnnotation)) haveMultipleInstanceOf.add(sourceLineAnnotation); } } BitSet linesMentionedMultipleTimes = ClassContext.linesMentionedMultipleTimes(method); LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool()); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); InstructionHandle handle = location.getHandle(); int pc = handle.getPosition(); Instruction ins = handle.getInstruction(); if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF)) continue; if (handle.getNext() == null) continue; Instruction nextIns = handle.getNext().getInstruction(); boolean isCast = ins instanceof CHECKCAST; String kind = isCast ? "checkedCast" : "instanceof"; int occurrences = cfg.getLocationsContainingInstructionWithOffset( pc).size(); boolean split = occurrences > 1; if (lineNumberTable != null) { int line = lineNumberTable.getSourceLine(handle.getPosition()); if (line > 0 && linesMentionedMultipleTimes.get(line)) split=true; } IsNullValueFrame nullFrame = isNullDataflow.getFactAtLocation(location); if (!nullFrame.isValid()) continue; IsNullValue operandNullness = nullFrame.getTopValue(); if (DEBUG) { System.out .println(kind + " at pc: " + pc + " in " + methodName); System.out.println(" occurrences: " + occurrences); System.out.println("XXX: " + operandNullness); } if (split && !isCast) { // don't report this case; it might be infeasible due to inlining continue; } TypeFrame frame = typeDataflow.getFactAtLocation(location); if (!frame.isValid()) { // This basic block is probably dead continue; } Type operandType = frame.getTopValue(); if (operandType.equals(TopType.instance())) { // unreachable continue; } boolean operandTypeIsExact = frame.isExact(frame.getStackLocation(0)); Type castType = ((TypedInstruction) ins).getType(cpg); if (!(castType instanceof ReferenceType)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -