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

📄 unconditionalvaluederefanalysis.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * FindBugs - Find Bugs in Java programs * Copyright (C) 2006, University of Maryland *  * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */package edu.umd.cs.findbugs.ba.deref;import java.util.Set;import org.apache.bcel.classfile.Method;import org.apache.bcel.generic.ARETURN;import org.apache.bcel.generic.FieldInstruction;import org.apache.bcel.generic.Instruction;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.InvokeInstruction;import org.apache.bcel.generic.MethodGen;import org.apache.bcel.generic.PUTFIELD;import org.apache.bcel.generic.PUTSTATIC;import edu.umd.cs.findbugs.SystemProperties;import edu.umd.cs.findbugs.annotations.CheckForNull;import edu.umd.cs.findbugs.ba.AnalysisContext;import edu.umd.cs.findbugs.ba.AssertionMethods;import edu.umd.cs.findbugs.ba.BackwardDataflowAnalysis;import edu.umd.cs.findbugs.ba.BasicBlock;import edu.umd.cs.findbugs.ba.CFG;import edu.umd.cs.findbugs.ba.CFGBuilderException;import edu.umd.cs.findbugs.ba.ClassContext;import edu.umd.cs.findbugs.ba.Dataflow;import edu.umd.cs.findbugs.ba.DataflowAnalysisException;import edu.umd.cs.findbugs.ba.DataflowTestDriver;import edu.umd.cs.findbugs.ba.DepthFirstSearch;import edu.umd.cs.findbugs.ba.Edge;import edu.umd.cs.findbugs.ba.EdgeTypes;import edu.umd.cs.findbugs.ba.Hierarchy;import edu.umd.cs.findbugs.ba.JavaClassAndMethod;import edu.umd.cs.findbugs.ba.Location;import edu.umd.cs.findbugs.ba.NullnessAnnotation;import edu.umd.cs.findbugs.ba.NullnessAnnotationDatabase;import edu.umd.cs.findbugs.ba.ReverseDepthFirstSearch;import edu.umd.cs.findbugs.ba.SignatureParser;import edu.umd.cs.findbugs.ba.XFactory;import edu.umd.cs.findbugs.ba.XField;import edu.umd.cs.findbugs.ba.XMethod;import edu.umd.cs.findbugs.ba.npe.IsNullConditionDecision;import edu.umd.cs.findbugs.ba.npe.IsNullValue;import edu.umd.cs.findbugs.ba.npe.IsNullValueDataflow;import edu.umd.cs.findbugs.ba.npe.IsNullValueFrame;import edu.umd.cs.findbugs.ba.npe.ParameterNullnessProperty;import edu.umd.cs.findbugs.ba.npe.ParameterNullnessPropertyDatabase;import edu.umd.cs.findbugs.ba.type.TypeDataflow;import edu.umd.cs.findbugs.ba.type.TypeFrame;import edu.umd.cs.findbugs.ba.vna.AvailableLoad;import edu.umd.cs.findbugs.ba.vna.ValueNumber;import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;/** * Dataflow analysis to find values unconditionally derefenced in the future. *  * @author David Hovemeyer */public class UnconditionalValueDerefAnalysis extends		BackwardDataflowAnalysis<UnconditionalValueDerefSet> {	public static final boolean DEBUG = SystemProperties.getBoolean("fnd.derefs.debug");	public static final boolean ASSUME_NONZERO_TRIP_LOOPS = SystemProperties.getBoolean("fnd.derefs.nonzerotrip");	  public static final boolean IGNORE_DEREF_OF_NCP = 		SystemProperties.getBoolean("fnd.derefs.ignoreNCP", false);	public static final boolean CHECK_ANNOTATIONS = 		SystemProperties.getBoolean("fnd.derefs.checkannotations", true);	public static final boolean CHECK_CALLS = 		SystemProperties.getBoolean("fnd.derefs.checkcalls", true);	public static final boolean DEBUG_CHECK_CALLS =		SystemProperties.getBoolean("fnd.derefs.checkcalls.debug");	private CFG cfg;	private final Method method;	private MethodGen methodGen;	private ValueNumberDataflow vnaDataflow;	private AssertionMethods assertionMethods;	private IsNullValueDataflow invDataflow;	private TypeDataflow typeDataflow;	/**	 * Constructor.	 * 	 * @param rdfs               the reverse depth-first-search (for the block order)	 * @param dfs TODO	 * @param cfg                the CFG for the method	 * @param method TODO	 * @param methodGen          the MethodGen for the method	 * @param vnaDataflow	 * @param assertionMethods   AssertionMethods for the analyzed class	 */	public UnconditionalValueDerefAnalysis(			ReverseDepthFirstSearch rdfs,			DepthFirstSearch dfs,			CFG cfg,			Method method,			MethodGen methodGen,			ValueNumberDataflow vnaDataflow, AssertionMethods assertionMethods			) {		super(rdfs, dfs);		this.cfg = cfg;		this.methodGen = methodGen;		this.method = method;		this.vnaDataflow = vnaDataflow;		this.assertionMethods = assertionMethods;		if (DEBUG) {			System.out.println("UnconditionalValueDerefAnalysis analysis " + methodGen.getClassName() + "." + methodGen.getName() + " : " + methodGen.getSignature());		}	}	/**	 * HACK: use the given is-null dataflow to clear deref sets for	 * values that are known to be definitely non-null on a branch.	 * 	 * @param invDataflow the IsNullValueDataflow to use	 */	public void clearDerefsOnNonNullBranches(IsNullValueDataflow invDataflow) {		this.invDataflow = invDataflow;	}	/**	 * 	 * 	 */	public void setTypeDataflow(TypeDataflow typeDataflow) {		this.typeDataflow= typeDataflow;	}	/* (non-Javadoc)	 * @see edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#isFactValid(java.lang.Object)	 */	@Override	public boolean isFactValid(UnconditionalValueDerefSet fact) {		return !fact.isTop() && !fact.isBottom();	}	/* (non-Javadoc)	 * @see edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#transferInstruction(org.apache.bcel.generic.InstructionHandle, edu.umd.cs.findbugs.ba.BasicBlock, java.lang.Object)	 */	@Override	public void transferInstruction(InstructionHandle handle,			BasicBlock basicBlock, UnconditionalValueDerefSet fact)			throws DataflowAnalysisException {		Instruction instruction = handle.getInstruction();		if (false && DEBUG) {			System.out.println("XXX: " + handle.getPosition() + " " + instruction);		}		   if (fact.isTop()) return;		Location location = new Location(handle, basicBlock);		// If this is a call to an assertion method,		// change the dataflow value to be TOP.		// We don't want to report future derefs that would		// be guaranteed only if the assertion methods		// returns normally.		// TODO: at some point, evaluate whether we should revisit this		if (isAssertion(handle) // || handle.getInstruction() instanceof ATHROW 				) {			if (DEBUG) System.out.println("MAKING BOTTOM0 AT: " + location);			fact.clear();			return;		}		// Get value number frame		ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(location);		if (!vnaFrame.isValid()) {			if (DEBUG) System.out.println("MAKING TOP1 AT: " + location);			// Probably dead code.			// Assume this location can't be reached.			makeFactTop(fact);			return;		}		// Check for calls to a method that unconditionally dereferences		// a parameter.  Mark any such arguments as derefs.		if (CHECK_CALLS && instruction instanceof InvokeInstruction) {			checkUnconditionalDerefDatabase(location, vnaFrame, fact);		}		// If this is a method call instruction,		// check to see if any of the parameters are @NonNull,		// and treat them as dereferences.		if (CHECK_ANNOTATIONS && instruction instanceof InvokeInstruction) {			checkNonNullParams(location, vnaFrame, fact);		}		if (CHECK_ANNOTATIONS && instruction instanceof ARETURN) {			XMethod thisMethod = XFactory.createXMethod(methodGen);			checkNonNullReturnValue(thisMethod, location, vnaFrame, fact);		}		if (CHECK_ANNOTATIONS && (instruction instanceof PUTFIELD || instruction instanceof PUTSTATIC)) {			checkNonNullPutField(location, vnaFrame, fact);		}		// Check to see if an instance value is dereferenced here		checkInstance(location, vnaFrame, fact);		if (false) fact.cleanDerefSet(location, vnaFrame);		if (DEBUG && fact.isTop()) System.out.println("MAKING TOP2 At: " + 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 {		InvokeInstruction inv = (InvokeInstruction) location.getHandle().getInstruction();		SignatureParser sigParser = new SignatureParser(inv.getSignature(methodGen.getConstantPool()));		int numParams = sigParser.getNumParameters();		if (numParams == 0) return;		ParameterNullnessPropertyDatabase database =			AnalysisContext.currentAnalysisContext().getUnconditionalDerefParamDatabase();		if (database == null) {			if (DEBUG_CHECK_CALLS) 				System.out.println("no database!");			return;		}		TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);		if (!typeFrame.isValid()) {			if (DEBUG_CHECK_CALLS) 				System.out.println("invalid type frame!");			return;		}		try {			Set<JavaClassAndMethod> targetSet = Hierarchy.resolveMethodCallTargets(					inv,					typeFrame,					methodGen.getConstantPool());			if (targetSet.isEmpty()) return;			if (DEBUG_CHECK_CALLS) System.out.println("target set size: " + targetSet.size());			// Compute the intersection of all properties			ParameterNullnessProperty derefParamSet = null;			for (JavaClassAndMethod target : targetSet) {				if (DEBUG_CHECK_CALLS) 					System.out.print("Checking: " + target + ": ");				ParameterNullnessProperty targetDerefParamSet = database.getProperty(target.toXMethod());				if (targetDerefParamSet == null) {					// Hmm...no information for this target.					// assume it doesn't dereference anything					if (DEBUG_CHECK_CALLS) 						System.out.println("==> no information, assume no guaranteed dereferences");					return;				}				if (DEBUG_CHECK_CALLS) {					System.out.println("==> " + targetDerefParamSet);				}				if (derefParamSet == null) {					derefParamSet = new ParameterNullnessProperty();					derefParamSet.copyFrom(targetDerefParamSet);				} else {					derefParamSet.intersectWith(targetDerefParamSet);				}			}			if (derefParamSet == null || derefParamSet.isEmpty()) {				if (DEBUG) System.out.println("** Nothing");				return;			}			if (DEBUG_CHECK_CALLS) {				System.out.println("** Summary of call @ " + location.getHandle().getPosition() 						+ ": " + derefParamSet);			}			IsNullValueFrame invFrame = invDataflow.getFactAtLocation(location);			if (invFrame != null && invFrame.isValid()) {				for (int i = 0; i < numParams; i++) {					if (!derefParamSet.isNonNull(i)) {						continue;					}						int argSlot = vnaFrame.getStackLocation(sigParser.getSlotsFromTopOfStackForParameter(i));					if (!reportDereference(invFrame, argSlot)) continue;					if (DEBUG_CHECK_CALLS)  System.out.println("  dereference @ " + location.getHandle().getPosition()  + " of parameter " + i);					fact.addDeref(vnaFrame.getValue(argSlot), location);				}			}		} catch (ClassNotFoundException e) {			AnalysisContext.reportMissingClass(e);		}	}	public static final boolean VERBOSE_NULLARG_DEBUG = SystemProperties.getBoolean("fnd.debug.nullarg.verbose");	/**	 * If this is a method call instruction,	 * check to see if any of the parameters are @NonNull,	 * and treat them as dereferences.	 * @param thisMethod TODO	 * @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 {		NullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase();		if (database == null) {			return;		}		IsNullValueFrame invFrame = invDataflow.getFactAtLocation(location);		if (!invFrame.isValid()) return;		if (database.getResolvedAnnotation(thisMethod, true) !=  NullnessAnnotation.NONNULL)			return;		IsNullValue value = invFrame.getTopValue();		if (value.isDefinitelyNotNull()) return;		if (value.isDefinitelyNull()) return;		ValueNumber vn = vnaFrame.getTopValue();		if (true)  fact.addDeref(vn, location);	}	/**	 * 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 {		NullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase();		if (database == null) {			return;		}		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);			}      		}	}	/**	 * 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 {		NullnessAnnotationDatabase database = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase();		if (database == null) {			return;		}		InvokeInstruction inv = (InvokeInstruction) location.getHandle().getInstruction(); 

⌨️ 快捷键说明

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