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

📄 bcpmethodreturncheck.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
字号:
/* * FindBugs - Find bugs in Java programs * Copyright (C) 2003-2005 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.detect;import java.util.ArrayList;import java.util.BitSet;import org.apache.bcel.Constants;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.Method;import org.apache.bcel.generic.ConstantPoolGen;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.InvokeInstruction;import org.apache.bcel.generic.MethodGen;import edu.umd.cs.findbugs.AnalysisLocal;import edu.umd.cs.findbugs.BugInstance;import edu.umd.cs.findbugs.BugReporter;import edu.umd.cs.findbugs.ByteCodePatternDetector;import edu.umd.cs.findbugs.JavaVersion;import edu.umd.cs.findbugs.StatelessDetector;import edu.umd.cs.findbugs.SystemProperties;import edu.umd.cs.findbugs.ba.ClassContext;import edu.umd.cs.findbugs.ba.bcp.ByteCodePattern;import edu.umd.cs.findbugs.ba.bcp.ByteCodePatternMatch;import edu.umd.cs.findbugs.ba.bcp.Invoke;import edu.umd.cs.findbugs.ba.bcp.MatchAny;import edu.umd.cs.findbugs.ba.bcp.Opcode;import edu.umd.cs.findbugs.ba.bcp.PatternElement;/** * This detector looks for places where the return value of a method * is suspiciously ignored.  Ignoring the return values from immutable * objects such as java.lang.String are a common and easily found type of bug. * * @author David Hovemeyer * @author Bill Pugh */public @Deprecated class BCPMethodReturnCheck extends ByteCodePatternDetector  {	private final BugReporter bugReporter;	private static final boolean CHECK_ALL = SystemProperties.getBoolean("mrc.checkall");	private static AnalysisLocal<ByteCodePattern> localByteCodePattern			= new AnalysisLocal<ByteCodePattern>();		private static AnalysisLocal<ArrayList<PatternElement>> localPatternElementList			= new AnalysisLocal<ArrayList<PatternElement>>();	@Override		 public ByteCodePattern  getPattern() {		ByteCodePattern  result = localByteCodePattern.get();		if (result == null) {			ArrayList<PatternElement> list = getPatternElementList();			PatternElement [] calls = list.toArray(new PatternElement[list.size()]);			// The ByteCodePattern which specifies the kind of code pattern			// we're looking for.  We want to match the invocation of certain methods			// followed by a POP or POP2 instruction.			result = new ByteCodePattern()				.add(new MatchAny(calls).label("call").setAllowTrailingEdges(false))				.add(new MatchAny(new PatternElement[]{new Opcode(Constants.POP), new Opcode(Constants.POP2)}));			localByteCodePattern.set(result);			}		return result;		}	public static  void		addMethodWhoseReturnMustBeChecked(String className, String methodName, 				String methodSig, int mode) {		ArrayList<PatternElement> list = getPatternElementList();		list.add(new Invoke(className, methodName, methodSig, mode, null));		localByteCodePattern.remove();		}	/**	 * Return List of PatternElement objects representing	 * method invocations requiring a return value check.	 */	private static 		ArrayList<PatternElement> getPatternElementList() {		ArrayList<PatternElement> list = localPatternElementList.get();		if (list != null) return list;		list = new ArrayList<PatternElement>();		// Standard return check methods		list.add(new Invoke("/.*", "equals",				"/\\(Ljava/lang/Object;\\)Z",				Invoke.INSTANCE, null));		list.add(new Invoke("java.lang.String", "/.*",				"/\\(.*\\)Ljava/lang/String;",				Invoke.INSTANCE, null));		list.add(new Invoke("java.lang.StringBuffer", "toString",				"()Ljava/lang/String;",				Invoke.INSTANCE,				null));		list.add(new Invoke("+java.lang.Thread", "<init>",				"/.*",				Invoke.CONSTRUCTOR,				null));		list.add(new Invoke("+java.lang.Throwable", "<init>",				"/.*",				Invoke.CONSTRUCTOR,				null));		list.add(new Invoke("java.security.MessageDigest",				"digest", "([B)[B",				Invoke.INSTANCE, null));		list.add(new Invoke("+java.sql.Connection", "/.*", "/.*",				Invoke.INSTANCE, null));//		list.add(new Invoke("+java.net.InetAddress", "/.*", "/.*",//		        Invoke.INSTANCE, null));		list.add(new Invoke("java.math.BigDecimal", "/.*", "/.*",				Invoke.INSTANCE, null));		list.add(new Invoke("java.math.BigInteger", "/.*", "/.*",				Invoke.INSTANCE, null));		list.add(new Invoke("+java.util.Enumeration", "hasMoreElements", "()Z", Invoke.INSTANCE, null));		list.add(new Invoke("+java.util.Iterator", "hasNext", "()Z", Invoke.INSTANCE, null));		list.add(new Invoke("java.io.File", "createNewFile", "()Z", Invoke.INSTANCE, null));		if (CHECK_ALL ||				JavaVersion.getRuntimeVersion().isSameOrNewerThan(JavaVersion.JAVA_1_5)) {			// Add JDK 1.5 and later return check functions			list.add(new Invoke("+java.util.concurrent.locks.ReadWriteLock",					"readLock",					"()Ljava/util/concurrent/locks/Lock;",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.ReadWriteLock",					"writeLock",					"()Ljava/util/concurrent/locks/Lock;",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.Condition",					"await",					"(JLjava/util/concurrent/TimeUnit;)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.Condition",					"awaitUtil",					"(Ljava/util/Date;)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.Condition",					"awaitNanos",					"(J)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.Semaphore",					"tryAcquire",					"(JLjava/util/concurrent/TimeUnit;)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.Semaphore",					"tryAcquire",					"()Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.Lock",					"tryLock",					"(JLjava/util/concurrent/TimeUnit;)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.Lock",					"newCondition",					"()Ljava/util/concurrent/locks/Condition;",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.locks.Lock",					"tryLock",					"()Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.Queue",					"offer",					"(Ljava/lang/Object;)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.BlockingQueue",					"offer",					"(Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Z",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.concurrent.BlockingQueue",					"poll",					"(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;",					Invoke.INSTANCE,					null));			list.add(new Invoke("+java.util.Queue",					"poll",					"()Ljava/lang/Object;",					Invoke.INSTANCE,					null));		}		String externalCheckReturnValues = SystemProperties.getProperty("checkReturnValues");		if (externalCheckReturnValues != null) {			String [] checks = externalCheckReturnValues.split("[|]");			for (String check : checks) {				String [] parts = check.split(":");				if (parts.length != 3) continue;				Invoke in =						new Invoke(parts[0], parts[1], parts[2], Invoke.INSTANCE, null);				list.add(in);			}			}		localPatternElementList.set(list);		return list;	}	/**	 * Constructor.	 *	 * @param bugReporter the BugReporter to report bug instances with	 */	public BCPMethodReturnCheck(BugReporter bugReporter) {		this.bugReporter = bugReporter;	}	@Override		 protected BugReporter getBugReporter() {		return bugReporter;	}	@Override		 public boolean prescreen(Method method, ClassContext classContext) {		// Pre-screen for methods with POP or POP2 bytecodes.		// This gives us a speedup close to 5X.		BitSet bytecodeSet = classContext.getBytecodeSet(method);		return bytecodeSet != null && (bytecodeSet.get(Constants.POP) || bytecodeSet.get(Constants.POP2));	}	@Override		 public void reportMatch(ClassContext classContext, Method method, ByteCodePatternMatch match) {		MethodGen methodGen = classContext.getMethodGen(method);		if (methodGen == null) return;		JavaClass javaClass = classContext.getJavaClass();		InstructionHandle call = match.getLabeledInstruction("call");		// Ignore inner-class access methods		InvokeInstruction inv = (InvokeInstruction) call.getInstruction();		ConstantPoolGen cp = methodGen.getConstantPool();		String calledMethodName = inv.getMethodName(cp);		if (calledMethodName.startsWith("access$")				|| calledMethodName.startsWith("access+"))			return;		/*		System.out.println("Found " + calledMethodName);		System.out.println(inv.getSignature(cp));		System.out.println(inv.getClassName(cp));		*/		String calledMethodClass = inv.getClassName(cp);		if (inv.getSignature(cp).endsWith("V") && !calledMethodName.equals("<init>"))			return;		/*		if (calledMethodClass.equals(javaClass.getClassName()))			return;		*/		String sourceFile = javaClass.getSourceFileName();		/*		System.out.println("CalledMethodClass: " + calledMethodClass);		System.out.println("CalledMethodName: " + calledMethodName);		*/		int priority = HIGH_PRIORITY;		if (calledMethodName.equals("createNewFile"))			priority = LOW_PRIORITY;		if ( calledMethodClass.startsWith("java.lang")			|| calledMethodClass.startsWith("java.math")				|| calledMethodClass.endsWith("Error")				|| calledMethodClass.endsWith("Exception"))			priority--;		if (calledMethodClass.equals(javaClass.getClassName()))			priority++;		String calledPackage = extractPackageName(calledMethodClass);		String callingPackage = extractPackageName(javaClass.getClassName());		if (calledPackage.length() > 0				&& callingPackage.length() > 0				&& (calledPackage.startsWith(callingPackage)				|| callingPackage.startsWith(calledPackage)))			priority++;		// System.out.println("priority: " + priority);		bugReporter.reportBug(new BugInstance(this, "RV_RETURN_VALUE_IGNORED2",				priority)				.addClassAndMethod(methodGen, sourceFile)				.addCalledMethod(methodGen, inv)				.addSourceLine(classContext, methodGen, sourceFile, call));	}	public static String extractPackageName(String className) {		int i = className.lastIndexOf('.');		if (i == -1) return "";		return className.substring(0, i);	}}// vim:ts=4

⌨️ 快捷键说明

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