1 package edu.umd.cs.findbugs.detect; 2 3 import java.util.BitSet ; 4 import java.util.Iterator ; 5 6 import org.apache.bcel.Constants; 7 import org.apache.bcel.classfile.Method; 8 import org.apache.bcel.generic.ConstantPoolGen; 9 import org.apache.bcel.generic.Instruction; 10 import org.apache.bcel.generic.InstructionHandle; 11 import org.apache.bcel.generic.InvokeInstruction; 12 import org.apache.bcel.generic.MethodGen; 13 import org.apache.bcel.generic.ReferenceType; 14 import org.apache.bcel.generic.Type; 15 16 import edu.umd.cs.findbugs.DeepSubtypeAnalysis; 17 import edu.umd.cs.findbugs.BugInstance; 18 import edu.umd.cs.findbugs.BugReporter; 19 import edu.umd.cs.findbugs.Detector; 20 import edu.umd.cs.findbugs.SourceLineAnnotation; 21 import edu.umd.cs.findbugs.ba.CFG; 22 import edu.umd.cs.findbugs.ba.CFGBuilderException; 23 import edu.umd.cs.findbugs.ba.ClassContext; 24 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 25 import edu.umd.cs.findbugs.ba.Location; 26 import edu.umd.cs.findbugs.ba.type.NullType; 27 import edu.umd.cs.findbugs.ba.type.TopType; 28 import edu.umd.cs.findbugs.ba.type.TypeDataflow; 29 import edu.umd.cs.findbugs.ba.type.TypeFrame; 30 31 public class FindNonSerializableValuePassedToWriteObject implements Detector { 32 33 private BugReporter bugReporter; 34 35 private static final boolean DEBUG = false; 36 37 public FindNonSerializableValuePassedToWriteObject(BugReporter bugReporter) { 38 this.bugReporter = bugReporter; 39 } 40 41 public void visitClassContext(ClassContext classContext) { 42 Method[] methodList = classContext.getJavaClass().getMethods(); 43 44 for (Method method : methodList) { 45 if (method.getCode() == null) 46 continue; 47 48 try { 49 analyzeMethod(classContext, method); 50 } catch (CFGBuilderException e) { 51 bugReporter.logError("Detector " + this.getClass().getName() 52 + " caught exception", e); 53 } catch (DataflowAnalysisException e) { 54 } 56 } 57 } 58 59 private void analyzeMethod(ClassContext classContext, Method method) 60 throws CFGBuilderException, DataflowAnalysisException { 61 MethodGen methodGen = classContext.getMethodGen(method); 62 if (methodGen == null) 63 return; 64 BitSet bytecodeSet = classContext.getBytecodeSet(method); 65 if (bytecodeSet == null) return; 66 if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST)) 68 return; 69 CFG cfg = classContext.getCFG(method); 70 TypeDataflow typeDataflow = classContext.getTypeDataflow(method); 71 ConstantPoolGen cpg = classContext.getConstantPoolGen(); 72 73 String sourceFile = classContext.getJavaClass().getSourceFileName(); 74 if (DEBUG) { 75 String methodName = methodGen.getClassName() + "." 76 + methodGen.getName(); 77 System.out.println("Checking " + methodName); 78 } 79 80 for (Iterator <Location> i = cfg.locationIterator(); i.hasNext();) { 81 Location location = i.next(); 82 InstructionHandle handle = location.getHandle(); 83 int pc = handle.getPosition(); 84 Instruction ins = handle.getInstruction(); 85 86 if (!(ins instanceof InvokeInstruction)) 87 continue; 88 89 InvokeInstruction invoke = (InvokeInstruction) ins; 90 String mName = invoke.getMethodName(cpg); 91 if (!mName.equals("writeObject")) 92 continue; 93 String cName = invoke.getClassName(cpg); 94 if (!cName.equals("java.io.ObjectOutput") 95 && !cName.equals("java.io.ObjectOutputStream")) 96 continue; 97 98 TypeFrame frame = typeDataflow.getFactAtLocation(location); 99 if (!frame.isValid()) { 100 continue; 102 } 103 Type operandType = frame.getTopValue(); 104 105 if (operandType.equals(TopType.instance())) { 106 continue; 108 } 109 if (!(operandType instanceof ReferenceType)) { 110 continue; 112 } 113 ReferenceType refType = (ReferenceType) operandType; 114 115 if (refType.equals(NullType.instance())) { 116 continue; 117 } 118 String refSig = refType.getSignature(); 119 120 try { 121 122 double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(refSig); 123 124 if (isSerializable < 0.9) { 125 double isRemote = DeepSubtypeAnalysis.isDeepRemote(refSig); 126 if (isSerializable < isRemote) 127 isSerializable = isRemote; 128 } 129 130 if (isSerializable < 0.9) { 131 SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation 132 .fromVisitedInstruction(classContext, methodGen, 133 sourceFile, handle); 134 135 bugReporter 136 .reportBug(new BugInstance( 137 this, 138 "DMI_NONSERIALIZABLE_OBJECT_WRITTEN", 139 isSerializable < 0.15 ? HIGH_PRIORITY 140 : isSerializable > 0.5 ? LOW_PRIORITY 141 : NORMAL_PRIORITY) 142 .addClassAndMethod(methodGen, sourceFile) 143 .addClass(DeepSubtypeAnalysis.getComponentClass(refSig)) 144 .addSourceLine(sourceLineAnnotation) 145 ); 146 } 147 } catch (ClassNotFoundException e) { 148 } 150 } 151 } 152 153 public void report() { 154 } 155 156 } 157 | Popular Tags |