public static Set<ValueNumber> checkAllNonNullParams( Location location, ValueNumberFrame vnaFrame, ConstantPoolGen constantPool, @CheckForNull Method method, @CheckForNull IsNullValueDataflow invDataflow, TypeDataflow typeDataflow) throws DataflowAnalysisException { IsNullValueFrame invFrame = null; if (invDataflow != null) { invFrame = invDataflow.getFactAtLocation(location); } Set<ValueNumber> result1 = checkNonNullParams(location, vnaFrame, constantPool, method, invFrame); Set<ValueNumber> result2 = checkUnconditionalDerefDatabase(location, vnaFrame, constantPool, invFrame, typeDataflow); if (result1.isEmpty()) { return result2; } if (result2.isEmpty()) { return result1; } result1.addAll(result2); return result1; }
/** * If this is a putfield or putstatic instruction, check to see if the field is @NonNull, and * treat it as dereferences. * * @param location the Location of the instruction * @param vnaFrame the ValueNumberFrame at the Location of the instruction * @param fact the dataflow value to modify * @throws DataflowAnalysisException */ private void checkNonNullPutField( Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { INullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase(); FieldInstruction fieldIns = (FieldInstruction) location.getHandle().getInstruction(); XField field = XFactory.createXField(fieldIns, methodGen.getConstantPool()); char firstChar = field.getSignature().charAt(0); if (firstChar != 'L' && firstChar != '[') { return; } NullnessAnnotation resolvedAnnotation = database.getResolvedAnnotation(field, true); if (resolvedAnnotation == NullnessAnnotation.NONNULL) { IsNullValueFrame invFrame = invDataflow.getFactAtLocation(location); if (!invFrame.isValid()) { return; } IsNullValue value = invFrame.getTopValue(); if (reportDereference(value)) { ValueNumber vn = vnaFrame.getTopValue(); fact.addDeref(vn, location); } } }
private void handleNullCheck( Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { if (reportPotentialDereference(location, invDataflow.getFactAtLocation(location))) { ValueNumber vn = vnaFrame.getTopValue(); fact.addDeref(vn, location); } }
/** * If this is a method call instruction, check to see if any of the parameters are @NonNull, and * treat them as dereferences. * * @param location the Location of the instruction * @param vnaFrame the ValueNumberFrame at the Location of the instruction * @param fact the dataflow value to modify * @throws DataflowAnalysisException */ private void checkNonNullParams( Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { ConstantPoolGen constantPool = methodGen.getConstantPool(); Set<ValueNumber> nonNullParams = checkNonNullParams( location, vnaFrame, constantPool, method, invDataflow.getFactAtLocation(location)); for (ValueNumber vn : nonNullParams) { fact.addDeref(vn, location); } }
/** * Check method call at given location to see if it unconditionally dereferences a parameter. Mark * any such arguments as derefs. * * @param location the Location of the method call * @param vnaFrame ValueNumberFrame at the Location * @param fact the dataflow value to modify * @throws DataflowAnalysisException */ private void checkUnconditionalDerefDatabase( Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { ConstantPoolGen constantPool = methodGen.getConstantPool(); for (ValueNumber vn : checkUnconditionalDerefDatabase( location, vnaFrame, constantPool, invDataflow.getFactAtLocation(location), typeDataflow)) { fact.addDeref(vn, location); } }
/** * If this is a method call instruction, check to see if any of the parameters are @NonNull, and * treat them as dereferences. * * @param location the Location of the instruction * @param vnaFrame the ValueNumberFrame at the Location of the instruction * @param fact the dataflow value to modify * @throws DataflowAnalysisException */ private void checkNonNullReturnValue( XMethod thisMethod, Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { INullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase(); if (database.getResolvedAnnotation(thisMethod, true) != NullnessAnnotation.NONNULL) { return; } if (reportPotentialDereference(location, invDataflow.getFactAtLocation(location))) { ValueNumber vn = vnaFrame.getTopValue(); fact.addDeref(vn, location); } }
/** * Clear deref sets of values if this edge is the non-null branch of an if comparison. * * @param fact a datflow fact * @param edge edge to check * @return possibly-modified dataflow fact */ private @CheckForNull ValueNumber findValueKnownNonnullOnBranch( UnconditionalValueDerefSet fact, Edge edge) { IsNullValueFrame invFrame = invDataflow.getResultFact(edge.getSource()); if (!invFrame.isValid()) { return null; } IsNullConditionDecision decision = invFrame.getDecision(); if (decision == null) { return null; } IsNullValue inv = decision.getDecision(edge.getType()); if (inv == null || !inv.isDefinitelyNotNull()) { return null; } ValueNumber value = decision.getValue(); if (DEBUG) { System.out.println("Value number " + value + " is known nonnull on " + edge); } return value; }
/** * 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); }