/** * Check to see if the instruction has a null check associated with it, and if so, add a * dereference. * * @param location the Location of the instruction * @param vnaFrame ValueNumberFrame at the Location of the instruction * @param fact the dataflow value to modify * @throws DataflowAnalysisException */ private void checkInstance( Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { // See if this instruction has a null check. // If it does, the fall through predecessor will be // identify itself as the null check. if (!location.isFirstInstructionInBasicBlock()) { return; } if (invDataflow == null) { return; } BasicBlock fallThroughPredecessor = cfg.getPredecessorWithEdgeType(location.getBasicBlock(), EdgeTypes.FALL_THROUGH_EDGE); if (fallThroughPredecessor == null || !fallThroughPredecessor.isNullCheck()) { return; } // Get the null-checked value ValueNumber vn = vnaFrame.getInstance(location.getHandle().getInstruction(), methodGen.getConstantPool()); // Ignore dereferences of this if (!methodGen.isStatic()) { ValueNumber v = vnaFrame.getValue(0); if (v.equals(vn)) { return; } } if (vn.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) { return; } IsNullValueFrame startFact = null; startFact = invDataflow.getStartFact(fallThroughPredecessor); if (!startFact.isValid()) { return; } int slot = startFact.getInstanceSlot( location.getHandle().getInstruction(), methodGen.getConstantPool()); if (!reportDereference(startFact, slot)) { return; } if (DEBUG) { System.out.println("FOUND GUARANTEED DEREFERENCE"); System.out.println("Load: " + vnaFrame.getLoad(vn)); System.out.println("Pred: " + fallThroughPredecessor); System.out.println("startFact: " + startFact); System.out.println("Location: " + location); System.out.println("Value number frame: " + vnaFrame); System.out.println("Dereferenced valueNumber: " + vn); System.out.println("invDataflow: " + startFact); System.out.println("IGNORE_DEREF_OF_NCP: " + IGNORE_DEREF_OF_NCP); } // Mark the value number as being dereferenced at this location fact.addDeref(vn, location); }
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Const.ACC_BRIDGE) == Const.ACC_BRIDGE) { return; } CFG cfg = classContext.getCFG(method); ConstantPoolGen cpg = classContext.getConstantPoolGen(); TypeDataflow typeDataflow = classContext.getTypeDataflow(method); for (Iterator<BasicBlock> i = cfg.blockIterator(); i.hasNext(); ) { BasicBlock basicBlock = i.next(); // Check if it's a method invocation. if (!basicBlock.isExceptionThrower()) { continue; } InstructionHandle thrower = basicBlock.getExceptionThrower(); Instruction ins = thrower.getInstruction(); if (!(ins instanceof InvokeInstruction)) { continue; } InvokeInstruction inv = (InvokeInstruction) ins; boolean foundThrower = false; boolean foundNonThrower = false; if (inv instanceof INVOKEINTERFACE) { continue; } String className = inv.getClassName(cpg); Location loc = new Location(thrower, basicBlock); TypeFrame typeFrame = typeDataflow.getFactAtLocation(loc); XMethod primaryXMethod = XFactory.createXMethod(inv, cpg); // if (primaryXMethod.isAbstract()) continue; Set<XMethod> targetSet = null; try { if (className.startsWith("[")) { continue; } String methodSig = inv.getSignature(cpg); if (!methodSig.endsWith("V")) { continue; } targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, cpg); for (XMethod xMethod : targetSet) { if (DEBUG) { System.out.println("\tFound " + xMethod); } boolean isUnconditionalThrower = xMethod.isUnconditionalThrower() && !xMethod.isUnsupported() && !xMethod.isSynthetic(); if (isUnconditionalThrower) { foundThrower = true; if (DEBUG) { System.out.println("Found thrower"); } } else { foundNonThrower = true; if (DEBUG) { System.out.println("Found non thrower"); } } } } catch (ClassNotFoundException e) { analysisContext.getLookupFailureCallback().reportMissingClass(e); } boolean newResult = foundThrower && !foundNonThrower; if (newResult) { bugReporter.reportBug( new BugInstance(this, "TESTING", Priorities.NORMAL_PRIORITY) .addClassAndMethod(classContext.getJavaClass(), method) .addString("Call to method that always throws Exception") .addMethod(primaryXMethod) .describe(MethodAnnotation.METHOD_CALLED) .addSourceLine(classContext, method, loc)); } } }