/** * Creates a new instance of this Detector. * * @param aReporter * {@link BugReporter} instance to report found problems to. */ public StaticCalendarDetector(BugReporter aReporter) { reporter = aReporter; bugAccumulator = new BugAccumulator(reporter); }
private void accumulateBug() { if (pendingBug == null) { return; } bugAccumulator.accumulateBug(pendingBug, SourceLineAnnotation.fromVisitedInstruction(this, monitorEnterPC)); pendingBug = null; } }
@Override public void visitAfter(JavaClass obj) { accumulator.reportAccumulatedBugs(); }
@Override public void visitAfter(Code code) { if(bugAccumulator.getLastBugLocation() == null && !sawExcludedNSECall && noSideEffectMethods.useless(getMethodDescriptor())) { // Do not report UC_USELESS_VOID_METHOD if something was already reported inside the current method // it's likely that UC_USELESS_VOID_METHOD is just the consequence of the previous report bugAccumulator.accumulateBug(new BugInstance(this, "UC_USELESS_VOID_METHOD", code.getCode().length > 40 ? HIGH_PRIORITY : code.getCode().length > 15 ? NORMAL_PRIORITY : LOW_PRIORITY) .addClassAndMethod(getMethodDescriptor()), this); } sawExcludedNSECall = false; bugAccumulator.reportAccumulatedBugs(); }
absoluteValueAccumulator.accumulateBug(pendingAbsoluteValueBug, pendingAbsoluteValueBugSourceLine); pendingAbsoluteValueBug = null; pendingAbsoluteValueBugSourceLine = null; accumulator.reportAccumulatedBugs(); if (sawLoadOfMinValue) { absoluteValueAccumulator.clearBugs(); } else { absoluteValueAccumulator.reportAccumulatedBugs();
@Override public void visit(Code code) { if (getMethodSig().indexOf("Logger") == -1) { sawGetLogger = -1; loggerEscaped = loggerImported = false; super.visit(code); // make callbacks to sawOpcode for all opcodes /* if (false) { System.out.println(getFullyQualifiedMethodName()); System.out.printf("%d %s %s\n", sawGetLogger, loggerEscaped, loggerImported); } */ if (sawGetLogger >= 0 && !loggerEscaped && !loggerImported) { bugAccumulator.reportAccumulatedBugs(); } else { bugAccumulator.clearBugs(); } } }
@Override public void sawOpcode(int seen) { if (seen == Const.LDC || seen == Const.LDC_W || seen == Const.LDC2_W) { Constant c = getConstantRefOperand(); if (c instanceof ConstantFloat) { checkConst(((ConstantFloat) c).getBytes()); } else if (c instanceof ConstantDouble) { checkConst(((ConstantDouble) c).getBytes()); } return; } // Lower priority if the constant is put into array immediately or after the boxing: // this is likely to be just similar number in some predefined dataset (like lookup table) if(seen == Const.INVOKESTATIC && lastBug != null) { if (getNextOpcode() == Const.AASTORE && getNameConstantOperand().equals("valueOf") && (getClassConstantOperand().equals("java/lang/Double") || getClassConstantOperand().equals( "java/lang/Float"))) { lastBug = ((BugInstance)lastBug.clone()); lastBug.setPriority(lastPriority+1); bugAccumulator.forgetLastBug(); bugAccumulator.accumulateBug(lastBug, this); } } lastBug = null; }
/** * If feature is enabled, suppress warnings where there is at least one live * store on the line where the warning would be reported. * * @param accumulator * BugAccumulator containing warnings for method * @param liveStoreSourceLineSet * bitset of lines where at least one live store was seen */ private void suppressWarningsIfOneLiveStoreOnLine(BugAccumulator accumulator, BitSet liveStoreSourceLineSet) { if (!SUPPRESS_IF_AT_LEAST_ONE_LIVE_STORE_ON_LINE) { return; } // Eliminate any accumulated warnings for instructions // that (due to inlining) *can* be live stores. entryLoop: for (Iterator<? extends BugInstance> i = accumulator.uniqueBugs().iterator(); i.hasNext();) { for (SourceLineAnnotation annotation : accumulator.locations(i.next())) { if (liveStoreSourceLineSet.get(annotation.getStartLine())) { // This instruction can be a live store; don't report // it as a warning. i.remove(); continue entryLoop; } } } }
refComparisonList); } else if ( "assertFalse".equals(methodName) && "(Z)V".equals(methodSig)) { SourceLineAnnotation lastLocation = bugAccumulator.getLastBugLocation(); InstructionHandle prevHandle = location.getHandle().getPrev(); if (lastLocation != null && prevHandle != null && lastLocation.getEndBytecode() == prevHandle.getPosition()){ bugAccumulator.forgetLastBug(); if (DEBUG) { System.out.println("Forgetting last bug due to call to " + className +"." + methodName);
BugInstance bug = new BugInstance(this, "DM_BOXED_PRIMITIVE_TOSTRING", HIGH_PRIORITY).addClassAndMethod(this) .addCalledMethod(this).addMethod(preferred).describe(MethodAnnotation.SHOULD_CALL); accumulator.accumulateBug(bug, this); accumulator.accumulateBug(bug, this); } else if ("longValue".equals(called.getName()) && "java/lang/Long".equals(called.getClassDescriptor().getClassName()) accumulator.accumulateBug(bug, this); } else if("compareTo".equals(called.getName()) && "valueOf".equals(previousMethodCall.getName()) : HIGH_PRIORITY).addClassAndMethod(this).addCalledMethod(this).addMethod(shouldCall) .describe(MethodAnnotation.SHOULD_CALL); accumulator.accumulateBug(bug, this); .addString("Did you mean MICROS_PER_DAY").addInt(MICROS_PER_DAY_OVERFLOWED_AS_INT) .describe(IntAnnotation.INT_VALUE); accumulator.accumulateBug(bug, this); pendingAbsoluteValueBug = null; pendingAbsoluteValueBugSourceLine = null; absoluteValueAccumulator.clearBugs(); int year = (Integer) constant1; if (testingEnabled && year > 1900) { accumulator.accumulateBug( new BugInstance(this, "TESTING", HIGH_PRIORITY).addClassAndMethod(this) .addString("Comparison of getYear does understand that it returns year-1900")
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { // System.out.println("Checking " + method); CFG cfg = classContext.getCFG(method); LockDataflow lockDataflow = classContext.getLockDataflow(method); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); Instruction ins = location.getHandle().getInstruction(); if (!(ins instanceof INVOKESTATIC)) { continue; } if (!isSleep((INVOKESTATIC) ins, classContext.getConstantPoolGen())) { continue; } // System.out.println("Found sleep at " + location.getHandle()); LockSet lockSet = lockDataflow.getFactAtLocation(location); if (lockSet.getNumLockedObjects() > 0) { bugAccumulator.accumulateBug( new BugInstance(this, "SWL_SLEEP_WITH_LOCK_HELD", NORMAL_PRIORITY).addClassAndMethod( classContext.getJavaClass(), method), classContext, method, location); } } bugAccumulator.reportAccumulatedBugs(); }
} else if (d.priority > priority) { if (d.priority >= Priorities.LOW_PRIORITY) { reportBug(bug, d); d.allSource.clear();
@Override public void visitAfter(JavaClass obj) { bugAccumulator.reportAccumulatedBugs(); }
@Override public void visitAfter(Code code) { if(bugAccumulator.getLastBugLocation() == null && !sawExcludedNSECall && noSideEffectMethods.useless(getMethodDescriptor())) { // Do not report UC_USELESS_VOID_METHOD if something was already reported inside the current method // it's likely that UC_USELESS_VOID_METHOD is just the consequence of the previous report bugAccumulator.accumulateBug(new BugInstance(this, "UC_USELESS_VOID_METHOD", code.getCode().length > 40 ? HIGH_PRIORITY : code.getCode().length > 15 ? NORMAL_PRIORITY : LOW_PRIORITY) .addClassAndMethod(getMethodDescriptor()), this); } sawExcludedNSECall = false; bugAccumulator.reportAccumulatedBugs(); }
absoluteValueAccumulator.accumulateBug(pendingAbsoluteValueBug, pendingAbsoluteValueBugSourceLine); pendingAbsoluteValueBug = null; pendingAbsoluteValueBugSourceLine = null; accumulator.reportAccumulatedBugs(); if (sawLoadOfMinValue) { absoluteValueAccumulator.clearBugs(); } else { absoluteValueAccumulator.reportAccumulatedBugs();
@Override public void visit(Code obj) { if ("equals".equals(getMethodName()) && "(Ljava/lang/Object;)Z".equals(getMethodSig())) { super.visit(obj); if (AnalysisContext.currentAnalysisContext().isApplicationClass(getThisClass())) { bugAccumulator.reportAccumulatedBugs(); } bugAccumulator.clearBugs(); } }
@Override public void sawOpcode(int seen) { if (seen == LDC || seen == LDC_W || seen == LDC2_W) { Constant c = getConstantRefOperand(); if (c instanceof ConstantFloat) { checkConst(((ConstantFloat) c).getBytes()); } else if (c instanceof ConstantDouble) { checkConst(((ConstantDouble) c).getBytes()); } return; } // Lower priority if the constant is put into array immediately or after the boxing: // this is likely to be just similar number in some predefined dataset (like lookup table) if(seen == INVOKESTATIC && lastBug != null) { if (getNextOpcode() == AASTORE && getNameConstantOperand().equals("valueOf") && (getClassConstantOperand().equals("java/lang/Double") || getClassConstantOperand().equals( "java/lang/Float"))) { lastBug = ((BugInstance)lastBug.clone()); lastBug.setPriority(lastPriority+1); bugAccumulator.forgetLastBug(); bugAccumulator.accumulateBug(lastBug, this); } } lastBug = null; }
/** * If feature is enabled, suppress warnings where there is at least one live * store on the line where the warning would be reported. * * @param accumulator * BugAccumulator containing warnings for method * @param liveStoreSourceLineSet * bitset of lines where at least one live store was seen */ private void suppressWarningsIfOneLiveStoreOnLine(BugAccumulator accumulator, BitSet liveStoreSourceLineSet) { if (!SUPPRESS_IF_AT_LEAST_ONE_LIVE_STORE_ON_LINE) { return; } // Eliminate any accumulated warnings for instructions // that (due to inlining) *can* be live stores. entryLoop: for (Iterator<? extends BugInstance> i = accumulator.uniqueBugs().iterator(); i.hasNext();) { for (SourceLineAnnotation annotation : accumulator.locations(i.next())) { if (liveStoreSourceLineSet.get(annotation.getStartLine())) { // This instruction can be a live store; don't report // it as a warning. i.remove(); continue entryLoop; } } } }
refComparisonList); } else if ( "assertFalse".equals(methodName) && "(Z)V".equals(methodSig)) { SourceLineAnnotation lastLocation = bugAccumulator.getLastBugLocation(); InstructionHandle prevHandle = location.getHandle().getPrev(); if (lastLocation != null && prevHandle != null && lastLocation.getEndBytecode() == prevHandle.getPosition()){ bugAccumulator.forgetLastBug(); if (DEBUG) { System.out.println("Forgetting last bug due to call to " + className +"." + methodName);