⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 findnullderef.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
					}				} catch (CFGBuilderException e) {					assert true; // ignore it				}			}			if (DEBUG)				System.out.println("Target block is  "						+ (empty ? "empty" : "not empty"));			if (!empty) {				if (isThrower(target))					infeasibleEdgeSimplyThrowsException = true;			}			if (!empty && !previouslyDeadBlocks.get(target.getId())) {				if (DEBUG)					System.out.println("target was alive previously");				// Block was not dead before the null pointer analysis.				// See if it is dead now by inspecting the null value frame.				// If it's TOP, then the block became dead.				IsNullValueFrame invFrame = invDataflow.getStartFact(target);				createdDeadCode = invFrame.isTop();				if (DEBUG)					System.out.println("target is now "							+ (createdDeadCode ? "dead" : "alive"));			}		}		int priority;		boolean valueIsNull = true;		String warning;		if (redundantBranch.secondValue == null) {			if (redundantBranch.firstValue.isDefinitelyNull()) {				warning = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE";				priority = NORMAL_PRIORITY;			} else {				warning = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE";				valueIsNull = false;				priority = isChecked ? NORMAL_PRIORITY : LOW_PRIORITY;			}		} else {			boolean bothNull = redundantBranch.firstValue.isDefinitelyNull()					&& redundantBranch.secondValue.isDefinitelyNull();			if (redundantBranch.secondValue.isChecked())				isChecked = true;			if (redundantBranch.secondValue.wouldHaveBeenAKaboom()) {				wouldHaveBeenAKaboom = true;				locationOfKaBoom = redundantBranch.secondValue						.getLocationOfKaBoom();			}			if (bothNull) {				warning = "RCN_REDUNDANT_COMPARISON_TWO_NULL_VALUES";				priority = NORMAL_PRIORITY;			} else {				warning = "RCN_REDUNDANT_COMPARISON_OF_NULL_AND_NONNULL_VALUE";				priority = isChecked ? NORMAL_PRIORITY : LOW_PRIORITY;			}		}		if (wouldHaveBeenAKaboom) {			priority = HIGH_PRIORITY;			warning = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE";			if (locationOfKaBoom == null)				throw new NullPointerException("location of KaBoom is null");		}		if (DEBUG)			System.out.println(createdDeadCode + " "					+ infeasibleEdgeSimplyThrowsException + " " + valueIsNull					+ " " + priority);		if (createdDeadCode && !infeasibleEdgeSimplyThrowsException) {			priority += 0;		} else if (createdDeadCode && infeasibleEdgeSimplyThrowsException) {			// throw clause			if (valueIsNull)				priority += 0;			else				priority += 1;		} else {			// didn't create any dead code			priority += 1;		}		if (DEBUG) {			System.out.println("RCN" + priority + " "					+ redundantBranch.firstValue + " =? "					+ redundantBranch.secondValue + " : " + warning);			if (isChecked)				System.out.println("isChecked");			if (wouldHaveBeenAKaboom)				System.out.println("wouldHaveBeenAKaboom");			if (createdDeadCode)				System.out.println("createdDeadCode");		}		if (priority > LOW_PRIORITY) return;		BugAnnotation variableAnnotation = null;		try {			// Get the value number			ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(					method).getFactAtLocation(location);			if (vnaFrame.isValid()) {				Instruction ins = location.getHandle().getInstruction();				ValueNumber valueNumber = vnaFrame.getInstance(ins,						classContext.getConstantPoolGen());				if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))					return;				variableAnnotation = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method,						location, valueNumber, vnaFrame);			}		} catch (DataflowAnalysisException e) {			// ignore		} catch (CFGBuilderException e) {			// ignore		}		BugInstance bugInstance = new BugInstance(this, warning, priority)				.addClassAndMethod(classContext.getJavaClass(), method);		if (variableAnnotation != null)			bugInstance.add(variableAnnotation);		else			bugInstance.add(new LocalVariableAnnotation("?", -1, -1));		if (wouldHaveBeenAKaboom)			bugInstance.addSourceLine(classContext, method,					locationOfKaBoom);		bugInstance.addSourceLine(classContext, method,				location).describe("SOURCE_REDUNDANT_NULL_CHECK");		if (FindBugsAnalysisFeatures.isRelaxedMode()) {			WarningPropertySet propertySet = new WarningPropertySet();			WarningPropertyUtil.addPropertiesForLocation(propertySet,					classContext, method, location);			if (isChecked)				propertySet.addProperty(NullDerefProperty.CHECKED_VALUE);			if (wouldHaveBeenAKaboom)				propertySet						.addProperty(NullDerefProperty.WOULD_HAVE_BEEN_A_KABOOM);			if (createdDeadCode)				propertySet.addProperty(NullDerefProperty.CREATED_DEAD_CODE);			propertySet.decorateBugInstance(bugInstance);			priority = propertySet.computePriority(NORMAL_PRIORITY);			bugInstance.setPriority(priority);		}		bugReporter.reportBug(bugInstance);	}	// XXX	BugAnnotation getVariableAnnotation(Location location) {		BugAnnotation variableAnnotation = null;		try {			// Get the value number			ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(					method).getFactAtLocation(location);			if (vnaFrame.isValid()) {				Instruction ins = location.getHandle().getInstruction();				ValueNumber valueNumber = vnaFrame.getInstance(ins,						classContext.getConstantPoolGen());				if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))					return null;				variableAnnotation = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method,						location, valueNumber, vnaFrame);			}		} catch (DataflowAnalysisException e) {			// ignore		} catch (CFGBuilderException e) {			// ignore		}		return variableAnnotation;	}	/**	 * Determine whether or not given instruction is a goto.	 * 	 * @param instruction	 *            the instruction	 * @return true if the instruction is a goto, false otherwise	 */	private boolean isGoto(Instruction instruction) {		return instruction.getOpcode() == Constants.GOTO				|| instruction.getOpcode() == Constants.GOTO_W;	}	/*	 * (non-Javadoc)	 * 	 * @see edu.umd.cs.findbugs.ba.npe.NullDerefAndRedundantComparisonCollector#foundGuaranteedNullDeref(java.util.Set,	 *      java.util.Set, edu.umd.cs.findbugs.ba.vna.ValueNumber, boolean)	 */	public void foundGuaranteedNullDeref(@NonNull	Set<Location> assignedNullLocationSet, @NonNull	Set<Location> derefLocationSet, SortedSet<Location> doomedLocations,			ValueNumberDataflow vna, ValueNumber refValue,			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 = "NP_GUARANTEED_DEREF";		int priority = NORMAL_PRIORITY;		if (deref.isMethodReturnValue())			bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";		else {			if (deref.isAlwaysOnExceptionPath())				bugType += "_ON_EXCEPTION_PATH";			else priority = HIGH_PRIORITY;			if (!npeIfStatementCovered)				priority++;		}		// 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<Location>(assignedNullLocationSet);		else			sourceLocations = doomedLocations;		if (doomedLocations.isEmpty() || derefLocationSet.isEmpty())			return;		boolean derefOutsideCatchBlock = false;		for (Location loc : derefLocationSet)			if (!inCatchNullBlock(loc)) {				derefOutsideCatchBlock = true;				break;			}		boolean uniqueDereferenceLocations = false;		LineNumberTable table = method.getLineNumberTable();		if (table == null)			uniqueDereferenceLocations = true;		else {			BitSet linesMentionedMultipleTimes = ClassContext.linesMentionedMultipleTimes(method);			for(Location loc : derefLocationSet) {			  int lineNumber = table.getSourceLine(loc.getHandle().getPosition());			  if (!linesMentionedMultipleTimes.get(lineNumber)) uniqueDereferenceLocations = true;			}		}		if (!derefOutsideCatchBlock) {			if (!uniqueDereferenceLocations || skipIfInsideCatchNull())				return;			priority++;		}		if (!uniqueDereferenceLocations)			priority++;		// Create BugInstance		BitSet knownNull = new BitSet();		SortedSet<SourceLineAnnotation> knownNullLocations = new TreeSet<SourceLineAnnotation>();		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;		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);			} 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) {			if (pu.getReturnFromNonNullMethod()) {				bugType = "NP_NONNULL_RETURN_VIOLATION";				String methodName = method.getName();				String methodSig = method.getSignature();				if (methodName.equals("clone") && methodSig.equals("()Ljava/lang/Object;")) {					bugType = "NP_CLONE_COULD_RETURN_NULL";					priority = NORMAL_PRIORITY;				} else if (methodName.equals("toString") && methodSig.equals("()Ljava/lang/String;")) {					bugType = "NP_TOSTRING_COULD_RETURN_NULL";					priority = NORMAL_PRIORITY;				}			} else {				XField nonNullField = pu.getNonNullField();				if (nonNullField != null) {					storedField =  FieldAnnotation.fromXField( nonNullField );					bugType = "NP_STORE_INTO_NONNULL_FIELD";				} else {					XMethodParameter nonNullParameter = pu.getNonNullParameter();					if (nonNullParameter != null) {						XMethodParameter mp = nonNullParameter ;						invokedMethod =  MethodAnnotation.fromXMethod(mp.getMethod());						parameterNumber = mp.getParameterNumber();						bugType = "NP_NULL_PARAM_DEREF";					}				}			}			} else  if (!deref.isAlwaysOnExceptionPath())				bugType = "NP_NULL_ON_SOME_PATH";			else				bugType = "NP_NULL_ON_SOME_PATH_EXCEPTION";			if (deref.isMethodReturnValue())				bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";		}		BugInstance bugInstance = new BugInstance(this, bugType, priority)				.addClassAndMethod(classContext.getJavaClass(), method);		if (invokedMethod != null)			bugInstance.addMethod(invokedMethod).describe("METHOD_CALLED")			.addInt(parameterNumber+1).describe("INT_MAYBE_NULL_ARG");		if (storedField!= null)			bugInstance.addField(storedField).describe("FIELD_STORED");		bugInstance.add(variableAnnotation);		if (variableAnnotation instanceof FieldAnnotation)			bugInstance.describe("FIELD_CONTAINS_VALUE");		for (Location loc : derefLocationSet)			bugInstance.addSourceLine(classContext, method, loc).describe(getDescription(loc, refValue));		for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations)			bugInstance.add(sourceLineAnnotation).describe(			"SOURCE_LINE_KNOWN_NULL");		// If all deref locations are doomed		// (i.e., locations where a normal return is not possible),		// add a warning property indicating such.		// Are all derefs at doomed locations?		boolean allDerefsAtDoomedLocations = true;		for (Location derefLoc : derefLocationSet) {			if (!isDoomed(derefLoc)) {				allDerefsAtDoomedLocations = false;				break;			}		}		if (allDerefsAtDoomedLocations) {			// Add a WarningProperty			WarningPropertySet propertySet = new WarningPropertySet();			propertySet.addProperty(DoomedCodeWarningProperty.DOOMED_CODE);			propertySet.decorateBugInstance(bugInstance);		}		// Report it		bugReporter.reportBug(bugInstance);	}	private boolean isDoomed(Location loc) {		if (!MARK_DOOMED) {			return false;		}		ReturnPathTypeDataflow rptDataflow;		try {			rptDataflow = classContext.getReturnPathTypeDataflow(method);			ReturnPathType rpt = rptDataflow.getFactAtLocation(loc);			return  !rpt.canReturnNormally();		} catch (CheckedAnalysisException e) {			AnalysisContext.logError("Error getting return path type", e);			return false;		}	}	String getDescription(Location loc, ValueNumber refValue) {		PointerUsageRequiringNonNullValue pu;		try {			UsagesRequiringNonNullValues usages = classContext.getUsagesRequiringNonNullValues(method);			pu = usages.get(loc, refValue);			if (pu == null)  return "SOURCE_LINE_DEREF";			return pu.getDescription();		} catch (DataflowAnalysisException e) {		   AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);		   return "SOURCE_LINE_DEREF";		} catch (CFGBuilderException e) {			AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);			return "SOURCE_LINE_DEREF";		}	}	boolean inCatchNullBlock(Location loc) {		int pc = loc.getHandle().getPosition();		int catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),				"java/lang/NullPointerException", pc);		if (catchSize < Integer.MAX_VALUE)			return true;		catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),				"java/lang/Exception", pc);		if (catchSize < 5)			return true;		catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),				"java/lang/RuntimeException", pc);		if (catchSize < 5)			return true;		catchSize = Util.getSizeOfSurroundingTryBlock(classContext.getJavaClass().getConstantPool(), method.getCode(),				"java/lang/Throwable", pc);		if (catchSize < 5)			return true;		return false;	}}// vim:ts=4

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -