@Override
    public void foundGuaranteedNullDeref(@Nonnull
            Set<Location> assignedNullLocationSet, @Nonnull
            Set<Location> derefLocationSet, SortedSet<Location> doomedLocations, ValueNumberDataflow vna, ValueNumber refValue,
            @CheckForNull
            BugAnnotation variableAnnotation, NullValueUnconditionalDeref deref, boolean npeIfStatementCovered) {
        if (refValue.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
            return;
        }

        if (DEBUG) {
            System.out.println("Found guaranteed null deref in " + method.getName());
            for (Location loc : doomedLocations) {
                System.out.println("Doomed at " + loc);
            }
        }

        String bugType;

        int priority = npeIfStatementCovered ? HIGH_PRIORITY : NORMAL_PRIORITY;

        if (deref.isMethodReturnValue()) {
            if (deref.isReadlineValue()) {
                bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
            } else {
                bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";
            }
        } else if (derefLocationSet.size() > 1) {
            if (!deref.isAlwaysOnExceptionPath()) {
                bugType = "NP_GUARANTEED_DEREF";
            } else {
                bugType = "NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH";
            }
        } else if (!deref.isAlwaysOnExceptionPath()) {
            bugType = "NP_NULL_ON_SOME_PATH";
        } else {
            bugType = "NP_NULL_ON_SOME_PATH_EXCEPTION";
        }

        boolean allCallToAssertionMethod = !doomedLocations.isEmpty();
        for (Location loc : doomedLocations) {
            if (!callToAssertionMethod(loc)) {
                allCallToAssertionMethod = false;
            }
        }
        if (allCallToAssertionMethod) {
            return;
        }

        // Add Locations in the set of locations at least one of which
        // is guaranteed to be dereferenced

        SortedSet<Location> sourceLocations;
        if (doomedLocations.isEmpty() || doomedLocations.size() > 3 && doomedLocations.size() > assignedNullLocationSet.size()) {
            sourceLocations = new TreeSet<>(assignedNullLocationSet);
        } else {
            sourceLocations = doomedLocations;
        }

        if (doomedLocations.isEmpty() || derefLocationSet.isEmpty()) {
            return;
        }

        WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<>();

        addPropertiesForDereferenceLocations(propertySet, derefLocationSet, false);

        int minDereferencePC = minPC(derefLocationSet);
        int distance1 = minDereferencePC - maxPC(assignedNullLocationSet);
        int distance2 = minDereferencePC - maxPC(doomedLocations);
        int distance = Math.max(distance1, distance2);
        /*
        if (false) {
            System.out.printf("%9d %9d %9d RANGE %s.%s%s\n", distance, distance1, distance2, classContext.getClassDescriptor()
                    .toDottedClassName(), method.getName(), method.getSignature());
        }
         */

        // Create BugInstance

        BitSet knownNull = new BitSet();

        SortedSet<SourceLineAnnotation> knownNullLocations = new TreeSet<>();
        for (Location loc : sourceLocations) {
            SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc);
            if (sourceLineAnnotation == null) {
                continue;
            }
            int startLine = sourceLineAnnotation.getStartLine();
            if (startLine == -1) {
                knownNullLocations.add(sourceLineAnnotation);
            } else if (!knownNull.get(startLine)) {
                knownNull.set(startLine);
                knownNullLocations.add(sourceLineAnnotation);
            }
        }

        FieldAnnotation storedField = null;
        MethodAnnotation invokedMethod = null;
        XMethod invokedXMethod = null;
        int parameterNumber = -1;
        if (derefLocationSet.size() == 1) {

            Location loc = derefLocationSet.iterator().next();

            PointerUsageRequiringNonNullValue pu = null;
            try {
                UsagesRequiringNonNullValues usages = classContext.getUsagesRequiringNonNullValues(method);
                pu = usages.get(loc, refValue, vnaDataflow);
            } catch (DataflowAnalysisException e) {
                AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
            } catch (CFGBuilderException e) {
                AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
            }

            if (pu == null) {
                assert true; // nothing to do
            } else if (deref.isReadlineValue()) {
                bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
                priority = NORMAL_PRIORITY;
            } else if (deref.isMethodReturnValue() && !deref.isReadlineValue()) {
                bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";
                priority = NORMAL_PRIORITY;
            } else if (pu.isReturnFromNonNullMethod()) {
                bugType = "NP_NONNULL_RETURN_VIOLATION";
                String methodName = method.getName();
                String methodSig = method.getSignature();
                if ("clone".equals(methodName) && "()Ljava/lang/Object;".equals(methodSig)) {
                    bugType = "NP_CLONE_COULD_RETURN_NULL";
                    priority = NORMAL_PRIORITY;
                } else if ("toString".equals(methodName) && "()Ljava/lang/String;".equals(methodSig)) {
                    bugType = "NP_TOSTRING_COULD_RETURN_NULL";
                    priority = NORMAL_PRIORITY;
                }

            } else {
                XField f = pu.getNonNullField();
                if (f != null) {
                    storedField = FieldAnnotation.fromXField(f);
                    bugType = "NP_STORE_INTO_NONNULL_FIELD";
                } else {
                    XMethodParameter mp = pu.getNonNullParameter();
                    if (mp != null) {
                        invokedXMethod = mp.getMethod();
                        for (Location derefLoc : derefLocationSet) {
                            if (safeCallToPrimateParseMethod(invokedXMethod, derefLoc)) {
                                return;
                            }
                        }
                        invokedMethod = MethodAnnotation.fromXMethod(mp.getMethod());
                        if (mp.getParameterNumber() == 0
                                && TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(invokedXMethod)) {
                            return;
                        }
                        parameterNumber = mp.getParameterNumber();
                        bugType = "NP_NULL_PARAM_DEREF";
                    }
                }
            }
        }

        boolean hasManyNullTests = true;
        for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations) {
            if (!hasManyPreceedingNullTests(sourceLineAnnotation.getStartBytecode())) {
                hasManyNullTests = false;
            }
        }
        if (hasManyNullTests) {
            if ("NP_NULL_ON_SOME_PATH".equals(bugType) || "NP_GUARANTEED_DEREF".equals(bugType)) {
                bugType = "NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE";
            } else {
                priority++;
            }
        }

        BugInstance bugInstance = new BugInstance(this, bugType, priority).addClassAndMethod(classContext.getJavaClass(), method);
        if (invokedMethod != null) {
            assert invokedXMethod != null;
            XMethod i = invokedXMethod.resolveAccessMethodForMethod();
            if (i != invokedXMethod) {
                bugInstance.addMethod(i).describe(MethodAnnotation.METHOD_CALLED);
            } else {
                bugInstance.addMethod(invokedMethod).describe(MethodAnnotation.METHOD_CALLED)
                .addParameterAnnotation(parameterNumber, "INT_MAYBE_NULL_ARG");
            }
        }
        if (storedField != null) {
            bugInstance.addField(storedField).describe("FIELD_STORED");
        }
        bugInstance.addOptionalAnnotation(variableAnnotation);
        if (variableAnnotation instanceof FieldAnnotation) {
            bugInstance.describe("FIELD_CONTAINS_VALUE");
        }

        addPropertiesForDereferenceLocations(propertySet, derefLocationSet, false);

        if (deref.isAlwaysOnExceptionPath()) {
            propertySet.addProperty(NullDerefProperty.ALWAYS_ON_EXCEPTION_PATH);
        }

        if (!assignedNullLocationSet.isEmpty() && distance > 100) {
            propertySet.addProperty(NullDerefProperty.LONG_RANGE_NULL_SOURCE);
        }

        propertySet.decorateBugInstance(bugInstance);

        if ("NP_DEREFERENCE_OF_READLINE_VALUE".equals(bugType)) {

            int source = -9999;
            if (knownNullLocations.size() == 1) {
                source = knownNullLocations.iterator().next().getEndBytecode();
            }
            for (Location loc : derefLocationSet) {
                int pos = loc.getHandle().getPosition();
                if (pos != source + 3) {
                    // another detector
                    bugAccumulator.accumulateBug(bugInstance,
                            SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc));
                }
            }

        } else {
            for (Location loc : derefLocationSet) {
                bugInstance.addSourceLine(classContext, method, loc).describe(getDescription(loc, refValue));
            }

            if (sourceLocations == doomedLocations && assignedNullLocationSet.size() == 1) {
                Location assignedNull = assignedNullLocationSet.iterator().next();
                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method,
                        assignedNull);
                if (sourceLineAnnotation != null) {
                    int startLine = sourceLineAnnotation.getStartLine();
                    if (startLine > 0 && !knownNull.get(startLine)) {
                        bugInstance.add(sourceLineAnnotation).describe("SOURCE_LINE_NULL_VALUE");
                    }
                }

            }
            for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations) {
                bugInstance.add(sourceLineAnnotation).describe("SOURCE_LINE_KNOWN_NULL");
            }

            // Report it
            bugReporter.reportBug(bugInstance);
        }
    }
@ Override public void foundGuaranteedNullDeref ( @ Nonnull Set < Location > assignedNullLocationSet , @ Nonnull Set < Location > derefLocationSet , SortedSet < Location > doomedLocations , ValueNumberDataflow vna , ValueNumber refValue , @ CheckForNull BugAnnotation variableAnnotation , NullValueUnconditionalDeref deref , boolean npeIfStatementCovered ) { if ( refValue . hasFlag ( ValueNumber . CONSTANT_CLASS_OBJECT ) ) { return ; } if ( DEBUG ) { System . out . println ( "Found guaranteed null deref in " + method . getName ( ) ) ; for ( Location loc : doomedLocations ) { System . out . println ( "Doomed at " + loc ) ; } } String bugType ; int priority = npeIfStatementCovered ? HIGH_PRIORITY : NORMAL_PRIORITY ; if ( deref . isMethodReturnValue ( ) ) { if ( deref . isReadlineValue ( ) ) { bugType = "NP_DEREFERENCE_OF_READLINE_VALUE" ; } else { bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" ; } } else if ( derefLocationSet . size ( ) > 1 ) { if ( ! deref . isAlwaysOnExceptionPath ( ) ) { bugType = "NP_GUARANTEED_DEREF" ; } else { bugType = "NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH" ; } } else if ( ! deref . isAlwaysOnExceptionPath ( ) ) { bugType = "NP_NULL_ON_SOME_PATH" ; } else { bugType = "NP_NULL_ON_SOME_PATH_EXCEPTION" ; } boolean allCallToAssertionMethod = ! doomedLocations . isEmpty ( ) ; for ( Location loc : doomedLocations ) { if ( ! callToAssertionMethod ( loc ) ) { allCallToAssertionMethod = false ; } } if ( allCallToAssertionMethod ) { return ; } SortedSet < Location > sourceLocations ; if ( doomedLocations . isEmpty ( ) || doomedLocations . size ( ) > 3 && doomedLocations . size ( ) > assignedNullLocationSet . size ( ) ) { sourceLocations = new TreeSet < > ( assignedNullLocationSet ) ; } else { sourceLocations = doomedLocations ; } if ( doomedLocations . isEmpty ( ) || derefLocationSet . isEmpty ( ) ) { return ; } WarningPropertySet < WarningProperty > propertySet = new WarningPropertySet < > ( ) ; addPropertiesForDereferenceLocations ( propertySet , derefLocationSet , false ) ; int minDereferencePC = minPC ( derefLocationSet ) ; int distance1 = minDereferencePC - maxPC ( assignedNullLocationSet ) ; int distance2 = minDereferencePC - maxPC ( doomedLocations ) ; int distance = Math . max ( distance1 , distance2 ) ; BitSet knownNull = new BitSet ( ) ; SortedSet < SourceLineAnnotation > knownNullLocations = new TreeSet < > ( ) ; for ( Location loc : sourceLocations ) { SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation . fromVisitedInstruction ( classContext , method , loc ) ; if ( sourceLineAnnotation == null ) { continue ; } int startLine = sourceLineAnnotation . getStartLine ( ) ; if ( startLine == - 1 ) { knownNullLocations . add ( sourceLineAnnotation ) ; } else if ( ! knownNull . get ( startLine ) ) { knownNull . set ( startLine ) ; knownNullLocations . add ( sourceLineAnnotation ) ; } } FieldAnnotation storedField = null ; MethodAnnotation invokedMethod = null ; XMethod invokedXMethod = null ; int parameterNumber = - 1 ; if ( derefLocationSet . size ( ) == 1 ) { Location loc = derefLocationSet . iterator ( ) . next ( ) ; PointerUsageRequiringNonNullValue pu = null ; try { UsagesRequiringNonNullValues usages = classContext . getUsagesRequiringNonNullValues ( method ) ; pu = usages . get ( loc , refValue , vnaDataflow ) ; } catch ( DataflowAnalysisException e ) { AnalysisContext . logError ( "Error getting UsagesRequiringNonNullValues for " + method , e ) ; } catch ( CFGBuilderException e ) { AnalysisContext . logError ( "Error getting UsagesRequiringNonNullValues for " + method , e ) ; } if ( pu == null ) { assert true ; } else if ( deref . isReadlineValue ( ) ) { bugType = "NP_DEREFERENCE_OF_READLINE_VALUE" ; priority = NORMAL_PRIORITY ; } else if ( deref . isMethodReturnValue ( ) && ! deref . isReadlineValue ( ) ) { bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" ; priority = NORMAL_PRIORITY ; } else if ( pu . isReturnFromNonNullMethod ( ) ) { bugType = "NP_NONNULL_RETURN_VIOLATION" ; String methodName = method . getName ( ) ; String methodSig = method . getSignature ( ) ; if ( "clone" . equals ( methodName ) && "()Ljava/lang/Object;" . equals ( methodSig ) ) { bugType = "NP_CLONE_COULD_RETURN_NULL" ; priority = NORMAL_PRIORITY ; } else if ( "toString" . equals ( methodName ) && "()Ljava/lang/String;" . equals ( methodSig ) ) { bugType = "NP_TOSTRING_COULD_RETURN_NULL" ; priority = NORMAL_PRIORITY ; } } else { XField f = pu . getNonNullField ( ) ; if ( f != null ) { storedField = FieldAnnotation . fromXField ( f ) ; bugType = "NP_STORE_INTO_NONNULL_FIELD" ; } else { XMethodParameter mp = pu . getNonNullParameter ( ) ; if ( mp != null ) { invokedXMethod = mp . getMethod ( ) ; for ( Location derefLoc : derefLocationSet ) { if ( safeCallToPrimateParseMethod ( invokedXMethod , derefLoc ) ) { return ; } } invokedMethod = MethodAnnotation . fromXMethod ( mp . getMethod ( ) ) ; if ( mp . getParameterNumber ( ) == 0 && TypeQualifierNullnessAnnotationDatabase . assertsFirstParameterIsNonnull ( invokedXMethod ) ) { return ; } parameterNumber = mp . getParameterNumber ( ) ; bugType = "NP_NULL_PARAM_DEREF" ; } } } } boolean hasManyNullTests = true ; for ( SourceLineAnnotation sourceLineAnnotation : knownNullLocations ) { if ( ! hasManyPreceedingNullTests ( sourceLineAnnotation . getStartBytecode ( ) ) ) { hasManyNullTests = false ; } } if ( hasManyNullTests ) { if ( "NP_NULL_ON_SOME_PATH" . equals ( bugType ) || "NP_GUARANTEED_DEREF" . equals ( bugType ) ) { bugType = "NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE" ; } else { priority ++ ; } } BugInstance bugInstance = new BugInstance ( this , bugType , priority ) . addClassAndMethod ( classContext . getJavaClass ( ) , method ) ; if ( invokedMethod != null ) { assert invokedXMethod != null ; XMethod i = invokedXMethod . resolveAccessMethodForMethod ( ) ; if ( i != invokedXMethod ) { bugInstance . addMethod ( i ) . describe ( MethodAnnotation . METHOD_CALLED ) ; } else { bugInstance . addMethod ( invokedMethod ) . describe ( MethodAnnotation . METHOD_CALLED ) . addParameterAnnotation ( parameterNumber , "INT_MAYBE_NULL_ARG" ) ; } } if ( storedField != null ) { bugInstance . addField ( storedField ) . describe ( "FIELD_STORED" ) ; } bugInstance . addOptionalAnnotation ( variableAnnotation ) ; if ( variableAnnotation instanceof FieldAnnotation ) { bugInstance . describe ( "FIELD_CONTAINS_VALUE" ) ; } addPropertiesForDereferenceLocations ( propertySet , derefLocationSet , false ) ; if ( deref . isAlwaysOnExceptionPath ( ) ) { propertySet . addProperty ( NullDerefProperty . ALWAYS_ON_EXCEPTION_PATH ) ; } if ( ! assignedNullLocationSet . isEmpty ( ) && distance > 100 ) { propertySet . addProperty ( NullDerefProperty . LONG_RANGE_NULL_SOURCE ) ; } propertySet . decorateBugInstance ( bugInstance ) ; if ( "NP_DEREFERENCE_OF_READLINE_VALUE" . equals ( bugType ) ) { int source = - 9999 ; if ( knownNullLocations . size ( ) == 1 ) { source = knownNullLocations . iterator ( ) . next ( ) . getEndBytecode ( ) ; } for ( Location loc : derefLocationSet ) { int pos = loc . getHandle ( ) . getPosition ( ) ; if ( pos != source + 3 ) { bugAccumulator . accumulateBug ( bugInstance , SourceLineAnnotation . fromVisitedInstruction ( classContext , method , loc ) ) ; } } } else { for ( Location loc : derefLocationSet ) { bugInstance . addSourceLine ( classContext , method , loc ) . describe ( getDescription ( loc , refValue ) ) ; } if ( sourceLocations == doomedLocations && assignedNullLocationSet . size ( ) == 1 ) { Location assignedNull = assignedNullLocationSet . iterator ( ) . next ( ) ; SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation . fromVisitedInstruction ( classContext , method , assignedNull ) ; if ( sourceLineAnnotation != null ) { int startLine = sourceLineAnnotation . getStartLine ( ) ; if ( startLine > 0 && ! knownNull . get ( startLine ) ) { bugInstance . add ( sourceLineAnnotation ) . describe ( "SOURCE_LINE_NULL_VALUE" ) ; } } } for ( SourceLineAnnotation sourceLineAnnotation : knownNullLocations ) { bugInstance . add ( sourceLineAnnotation ) . describe ( "SOURCE_LINE_KNOWN_NULL" ) ; } bugReporter . reportBug ( bugInstance ) ; } }
/*
(non-Javadoc)

@seeedu.umd.cs.findbugs.ba.npe.NullDerefAndRedundantComparisonCollector#
foundGuaranteedNullDeref(java.util.Set, java.util.Set,
edu.umd.cs.findbugs.ba.vna.ValueNumber, boolean)