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

📄 findnullderef.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
		}	}	private void examineReturnInstruction(Location location)			throws DataflowAnalysisException, CFGBuilderException {		if (DEBUG_NULLRETURN) {			System.out.println("Checking null return at " + location);		}		IsNullValueDataflow invDataflow = classContext				.getIsNullValueDataflow(method);		IsNullValueFrame frame = invDataflow.getFactAtLocation(location);		ValueNumberFrame  vnaFrame = classContext.getValueNumberDataflow(method).getFactAtLocation(location);		if (!vnaFrame.isValid()) return;		ValueNumber valueNumber = vnaFrame.getTopValue();		if (!frame.isValid())			return;		IsNullValue tos = frame.getTopValue();		if (tos.isDefinitelyNull()) {			BugAnnotation variable = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method,					location, valueNumber, vnaFrame);			String bugPattern = "NP_NONNULL_RETURN_VIOLATION";			int priority = NORMAL_PRIORITY;			if (tos.isDefinitelyNull() && !tos.isException())				priority = HIGH_PRIORITY;			String methodName = method.getName();			if (methodName.equals("clone")) {				bugPattern = "NP_CLONE_COULD_RETURN_NULL";				priority = NORMAL_PRIORITY;			} else if (methodName.equals("toString")) {				bugPattern = "NP_TOSTRING_COULD_RETURN_NULL";				priority = NORMAL_PRIORITY;			}			BugInstance warning = new BugInstance(this, bugPattern, priority)					.addClassAndMethod(classContext.getJavaClass(), method).addOptionalAnnotation(variable).addSourceLine(							classContext, method,							location);			bugReporter.reportBug(warning);		}	}	private void checkUnconditionallyDereferencedParam(Location location,			ConstantPoolGen cpg, TypeDataflow typeDataflow,			InvokeInstruction invokeInstruction, BitSet nullArgSet,			BitSet definitelyNullArgSet) throws DataflowAnalysisException,			ClassNotFoundException {		boolean caught = inCatchNullBlock(location);		if (caught && skipIfInsideCatchNull())			return;		// See what methods might be called here		TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);		Set<JavaClassAndMethod> targetMethodSet = Hierarchy				.resolveMethodCallTargets(invokeInstruction, typeFrame, cpg);		if (DEBUG_NULLARG) {			System.out.println("Possibly called methods: " + targetMethodSet);		}		// See if any call targets unconditionally dereference one of the null		// arguments		BitSet unconditionallyDereferencedNullArgSet = new BitSet();		List<JavaClassAndMethod> dangerousCallTargetList = new LinkedList<JavaClassAndMethod>();		List<JavaClassAndMethod> veryDangerousCallTargetList = new LinkedList<JavaClassAndMethod>();		for (JavaClassAndMethod targetMethod : targetMethodSet) {			if (DEBUG_NULLARG) {				System.out.println("For target method " + targetMethod);			}			ParameterNullnessProperty property = unconditionalDerefParamDatabase					.getProperty(targetMethod.toXMethod());			if (property == null)				continue;			if (DEBUG_NULLARG) {				System.out.println("\tUnconditionally dereferenced params: "						+ property);			}			BitSet targetUnconditionallyDereferencedNullArgSet = property					.getViolatedParamSet(nullArgSet);			if (targetUnconditionallyDereferencedNullArgSet.isEmpty())				continue;			dangerousCallTargetList.add(targetMethod);			unconditionallyDereferencedNullArgSet					.or(targetUnconditionallyDereferencedNullArgSet);			if (!property.getViolatedParamSet(definitelyNullArgSet).isEmpty())				veryDangerousCallTargetList.add(targetMethod);		}		if (dangerousCallTargetList.isEmpty())			return;		WarningPropertySet propertySet = new WarningPropertySet();		// See if there are any safe targets		Set<JavaClassAndMethod> safeCallTargetSet = new HashSet<JavaClassAndMethod>();		safeCallTargetSet.addAll(targetMethodSet);		safeCallTargetSet.removeAll(dangerousCallTargetList);		if (safeCallTargetSet.isEmpty()) {			propertySet					.addProperty(NullArgumentWarningProperty.ALL_DANGEROUS_TARGETS);			if (dangerousCallTargetList.size() == 1) {				propertySet						.addProperty(NullArgumentWarningProperty.MONOMORPHIC_CALL_SITE);			}		}		// Call to private method? In theory there should be only one possible		// target.		boolean privateCall = safeCallTargetSet.isEmpty()				&& dangerousCallTargetList.size() == 1				&& dangerousCallTargetList.get(0).getMethod().isPrivate();		String bugType;		int priority;		if (privateCall				|| invokeInstruction.getOpcode() == Constants.INVOKESTATIC				|| invokeInstruction.getOpcode() == Constants.INVOKESPECIAL) {			bugType = "NP_NULL_PARAM_DEREF_NONVIRTUAL";			priority = HIGH_PRIORITY;		} else if (safeCallTargetSet.isEmpty()) {			bugType = "NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS";			priority = NORMAL_PRIORITY;		} else {		  return;		}		if (caught)			priority++;		if (dangerousCallTargetList.size() > veryDangerousCallTargetList.size())			priority++;		else			propertySet					.addProperty(NullArgumentWarningProperty.ACTUAL_PARAMETER_GUARANTEED_NULL);		BugInstance warning = new BugInstance(this,bugType, priority)				.addClassAndMethod(classContext.getJavaClass(), method).addMethod(						XFactory.createXMethod(invokeInstruction, cpg))				.describe("METHOD_CALLED").addSourceLine(classContext,						method,  location);		// Check which params might be null		addParamAnnotations(location,				definitelyNullArgSet, unconditionallyDereferencedNullArgSet, propertySet, warning);		if (bugType.equals("NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS")) {			// Add annotations for dangerous method call targets			for (JavaClassAndMethod dangerousCallTarget : veryDangerousCallTargetList) {				warning.addMethod(dangerousCallTarget).describe(				MethodAnnotation.METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL);			}			dangerousCallTargetList.removeAll(veryDangerousCallTargetList);			if (DEBUG_NULLARG) {				// Add annotations for dangerous method call targets				for (JavaClassAndMethod dangerousCallTarget : dangerousCallTargetList) {					warning.addMethod(dangerousCallTarget).describe(					MethodAnnotation.METHOD_DANGEROUS_TARGET);				}				// Add safe method call targets.				// This is useful to see which other call targets the analysis				// considered.				for (JavaClassAndMethod safeMethod : safeCallTargetSet) {					warning.addMethod(safeMethod).describe(MethodAnnotation.METHOD_SAFE_TARGET);				}			}}		decorateWarning(location, propertySet, warning);		bugReporter.reportBug(warning);	}	private void decorateWarning(Location location,			WarningPropertySet propertySet, BugInstance warning) {		if (FindBugsAnalysisFeatures.isRelaxedMode()) {			WarningPropertyUtil.addPropertiesForLocation(propertySet,					classContext, method, location);		}		propertySet.decorateBugInstance(warning);	}	private void addParamAnnotations(Location location,			BitSet definitelyNullArgSet, BitSet violatedParamSet,			WarningPropertySet propertySet, BugInstance warning)   {		ValueNumberFrame vnaFrame = null;		try {			vnaFrame = classContext.getValueNumberDataflow(method).getFactAtLocation(location);		} catch (DataflowAnalysisException e) {			AnalysisContext.logError("error", e);		} catch (CFGBuilderException e) {			AnalysisContext.logError("error",  e);		}		InvokeInstruction instruction = (InvokeInstruction) location.getHandle().getInstruction();		SignatureParser sigParser = new SignatureParser(instruction.getSignature(classContext.getConstantPoolGen()));		for (int i = violatedParamSet.nextSetBit(0); i >= 0; i = violatedParamSet.nextSetBit(i + 1)) {				boolean definitelyNull = definitelyNullArgSet.get(i);				if (definitelyNull) 					propertySet							.addProperty(NullArgumentWarningProperty.ARG_DEFINITELY_NULL);				ValueNumber valueNumber = null;				if (vnaFrame != null) 					try {					valueNumber = vnaFrame. getArgument(instruction, classContext.getConstantPoolGen(), i, sigParser );					BugAnnotation variableAnnotation = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method,							location, valueNumber, vnaFrame);					warning.addOptionalAnnotation(variableAnnotation);				} catch (DataflowAnalysisException e) {					AnalysisContext.logError("error", e);				}				// Note: we report params as being indexed starting from 1, not				// 0				warning.addInt(i + 1).describe(						definitelyNull ? "INT_NULL_ARG" : "INT_MAYBE_NULL_ARG");		}	}	/**	 * We have a method invocation in which a possibly or definitely null	 * parameter is passed. Check it against the library of nonnull annotations.	 * 	 * @param location	 * @param cpg	 * @param typeDataflow	 * @param invokeInstruction	 * @param nullArgSet	 * @param definitelyNullArgSet	 * @throws ClassNotFoundException	 */	private void checkNonNullParam(Location location, ConstantPoolGen cpg,			TypeDataflow typeDataflow, InvokeInstruction invokeInstruction,			BitSet nullArgSet, BitSet definitelyNullArgSet)			throws ClassNotFoundException {		boolean caught = inCatchNullBlock(location);		if (caught && skipIfInsideCatchNull())			return;		XMethod m = XFactory.createXMethod(invokeInstruction, cpg);		NullnessAnnotationDatabase db = AnalysisContext				.currentAnalysisContext().getNullnessAnnotationDatabase();		SignatureParser sigParser = new SignatureParser(invokeInstruction.getSignature(cpg));	   for (int i = nullArgSet.nextSetBit(0); i >= 0; i = nullArgSet				.nextSetBit(i + 1)) {			if (db.parameterMustBeNonNull(m, i)) {				boolean definitelyNull = definitelyNullArgSet.get(i);				if (DEBUG_NULLARG) {					System.out.println("QQQ2: " + i + " -- " + i + " is null");					System.out.println("QQQ nullArgSet: " + nullArgSet);					System.out.println("QQQ dnullArgSet: "							+ definitelyNullArgSet);				}				BugAnnotation variableAnnotation = null;				 try {					ValueNumberFrame vnaFrame = classContext.getValueNumberDataflow(method).getFactAtLocation(location);					ValueNumber valueNumber = vnaFrame. getArgument(invokeInstruction, cpg, i, sigParser );					variableAnnotation = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method,						   location, valueNumber, vnaFrame);				} catch (DataflowAnalysisException e) {				  AnalysisContext.logError("error", e);				} catch (CFGBuilderException e) {					AnalysisContext.logError("error", e);				}				int priority = definitelyNull ? HIGH_PRIORITY : NORMAL_PRIORITY;				if (caught)					priority++;				String description = definitelyNull ? "INT_NULL_ARG" : "INT_MAYBE_NULL_ARG";				BugInstance warning = new BugInstance(this,						"NP_NONNULL_PARAM_VIOLATION", priority)						.addClassAndMethod(classContext.getJavaClass(), method).addMethod(m)						.describe("METHOD_CALLED").addInt(i+1).describe(								description).addOptionalAnnotation(variableAnnotation).addSourceLine(								classContext, method,								location);				bugReporter.reportBug(warning);			}		}	}	public void report() {	}	public boolean skipIfInsideCatchNull() {		return classContext.getJavaClass().getClassName().indexOf("Test") >= 0				|| method.getName().indexOf("test") >= 0				|| method.getName().indexOf("Test") >= 0;	}	public void foundNullDeref(ClassContext classContext, Location location,			ValueNumber valueNumber, IsNullValue refValue,			ValueNumberFrame vnaFrame) {		WarningPropertySet propertySet = new WarningPropertySet();		if (valueNumber.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT))			return;		boolean onExceptionPath = refValue.isException();		if (onExceptionPath) {			propertySet.addProperty(GeneralWarningProperty.ON_EXCEPTION_PATH);		}		int pc = location.getHandle().getPosition();		BugAnnotation variable = NullDerefAndRedundantComparisonFinder.findAnnotationFromValueNumber(method,				location, valueNumber, vnaFrame);		boolean duplicated = false;		try {			CFG cfg = classContext.getCFG(method);			duplicated = cfg.getLocationsContainingInstructionWithOffset(pc)					.size() > 1;		} catch (CFGBuilderException e) {		}		boolean caught = inCatchNullBlock(location);		if (caught && skipIfInsideCatchNull())			return;		if (!duplicated && refValue.isDefinitelyNull()) {			String type = onExceptionPath ? "NP_ALWAYS_NULL_EXCEPTION"					: "NP_ALWAYS_NULL";			int priority = onExceptionPath ? NORMAL_PRIORITY : HIGH_PRIORITY;			if (caught)				priority++;			reportNullDeref(propertySet, classContext, method, location, type,					priority, variable);		} else if (refValue.mightBeNull() && refValue.isParamValue()) {			String type;			int priority = NORMAL_PRIORITY;			if (caught)				priority++;			if (method.getName().equals("equals")					&& method.getSignature()					.equals("(Ljava/lang/Object;)Z")) {				if (caught)					return;				type = "NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT";			} else				type = "NP_ARGUMENT_MIGHT_BE_NULL";			if (DEBUG)				System.out.println("Reporting null on some path: value="						+ refValue);			reportNullDeref(propertySet, classContext, method, location, type,					priority, variable);		}	}	private void reportNullDeref(WarningPropertySet propertySet,			ClassContext classContext, Method method, Location location,			String type, int priority, BugAnnotation variable) {		BugInstance bugInstance = new BugInstance(this, type, priority)				.addClassAndMethod(classContext.getJavaClass(), method);		if (variable != null)			bugInstance.add(variable);		else			bugInstance.add(new LocalVariableAnnotation("?", -1, -1));		bugInstance.addSourceLine(classContext, method, 				location).describe("SOURCE_LINE_DEREF");		if (FindBugsAnalysisFeatures.isRelaxedMode()) {			WarningPropertyUtil.addPropertiesForLocation(propertySet,					classContext, method, location);		}		if (isDoomed(location)) {			// Add a WarningProperty			propertySet.addProperty(DoomedCodeWarningProperty.DOOMED_CODE);		}		propertySet.decorateBugInstance(bugInstance);		bugReporter.reportBug(bugInstance);	}	public static boolean isThrower(BasicBlock target) {		InstructionHandle ins = target.getFirstInstruction();		int maxCount = 7;		while (ins != null) {			if (maxCount-- <= 0)				break;			Instruction i = ins.getInstruction();			if (i instanceof ATHROW) {				return true;			}			if (i instanceof InstructionTargeter					|| i instanceof ReturnInstruction)				return false;			ins = ins.getNext();		}		return false;	}	public void foundRedundantNullCheck(Location location,			RedundantBranch redundantBranch) {		boolean isChecked = redundantBranch.firstValue.isChecked();		boolean wouldHaveBeenAKaboom = redundantBranch.firstValue				.wouldHaveBeenAKaboom();		Location locationOfKaBoom = redundantBranch.firstValue				.getLocationOfKaBoom();		boolean createdDeadCode = false;		boolean infeasibleEdgeSimplyThrowsException = false;		Edge infeasibleEdge = redundantBranch.infeasibleEdge;		if (infeasibleEdge != null) {			if (DEBUG)				System.out.println("Check if " + redundantBranch						+ " creates dead code");			BasicBlock target = infeasibleEdge.getTarget();			if (DEBUG)				System.out.println("Target block is  "						+ (target.isExceptionThrower() ? " exception thrower"								: " not exception thrower"));			// If the block is empty, it probably doesn't matter that it was			// killed.			// FIXME: really, we should crawl the immediately reachable blocks			// starting at the target block to see if any of them are dead and			// nonempty.			boolean empty = !target.isExceptionThrower()					&& (target.isEmpty() || isGoto(target.getFirstInstruction()							.getInstruction()));			if (!empty) {				try {					if (classContext.getCFG(method).getNumIncomingEdges(target) > 1) {						if (DEBUG)							System.out									.println("Target of infeasible edge has multiple incoming edges");						empty = true;

⌨️ 快捷键说明

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