<commit_before>/*
 * fb-contrib - Auxiliary detectors for Java programs
 * Copyright (C) 2005-2014 <NAME>
 * 
 * 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 com.mebigfatguy.fbcontrib.detect;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.CodeException;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ExceptionTable;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.Type;

import com.mebigfatguy.fbcontrib.utils.BugType;
import com.mebigfatguy.fbcontrib.utils.RegisterUtils;
import com.mebigfatguy.fbcontrib.utils.SignatureUtils;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.ba.ClassContext;

/** looks for methods that catch checked exceptions, and throw unchecked
 * exceptions in their place. There are several levels of concern. Least
 * important are methods constrained by interface or super class contracts
 * not to throw checked exceptions but appear owned by the same author. Next
 * are methods constrained by interface or super class contracts and throw other
 * types of checked exceptions. Lastly are method not constrained by any interface
 * or superclass contract.
 */
public class ExceptionSoftening extends BytecodeScanningDetector 
{
	private static JavaClass runtimeClass;
	static {
		try {
			runtimeClass = Repository.lookupClass("java/lang/RuntimeException");
		} catch (ClassNotFoundException cnfe) {
			runtimeClass = null;
		}
	}
	private final BugReporter bugReporter;
	private OpcodeStack stack;
	private Map<Integer, CodeException> catchHandlerPCs;
	private List<CatchInfo> catchInfos;
	private LocalVariableTable lvt;
	private Map<String, Set<String>> constrainingInfo;
	private boolean isBooleanMethod;
	private boolean hasValidFalseReturn;
	private int catchFalseReturnPC;

	
    /** constructs a EXS detector given the reporter to report bugs on.

     * @param bugReporter the sync of bug reports
     */		
	public ExceptionSoftening(BugReporter bugReporter) {
		this.bugReporter = bugReporter;
	}
	
	/** overrides the visitor to reset the stack
	 * 
	 * @param classContext the context object of the currently parsed class
	 */
	@Override
	public void visitClassContext(ClassContext classContext) {
		try {
			if (runtimeClass != null) {
				stack = new OpcodeStack();
				super.visitClassContext(classContext);
			}
		} finally {
			stack = null;
		}
	}
		
	/** overrides the visitor to look for methods that catch checked exceptions
	 * and rethrow runtime exceptions
	 * 
	 * @param obj the context object of the currently parsed code block
	 */
	@Override
	public void visitCode(Code obj) {
		try {
			Method method = getMethod();
			isBooleanMethod = Type.BOOLEAN.equals(method.getReturnType());
			if (isBooleanMethod || prescreen(method)) {
				catchHandlerPCs = collectExceptions(obj.getExceptionTable());
				if (!catchHandlerPCs.isEmpty()) {
					stack.resetForMethodEntry(this);
					catchInfos = new ArrayList<CatchInfo>();
					lvt = method.getLocalVariableTable();
					constrainingInfo = null;
					hasValidFalseReturn = false;
					catchFalseReturnPC = -1;
					super.visitCode(obj);
					
					if (!hasValidFalseReturn && (catchFalseReturnPC >= 0)) {
						bugReporter.reportBug(new BugInstance(this, BugType.EXS_EXCEPTION_SOFTENING_RETURN_FALSE.name(), NORMAL_PRIORITY)<commit_msg>don't report ex->boolean when the method is 'isXXX', which admitely is a hack<commit_after>/*
 * fb-contrib - Auxiliary detectors for Java programs
 * Copyright (C) 2005-2014 <NAME>
 * 
 * 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 com.mebigfatguy.fbcontrib.detect;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.CodeException;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ExceptionTable;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.Type;

import com.mebigfatguy.fbcontrib.utils.BugType;
import com.mebigfatguy.fbcontrib.utils.RegisterUtils;
import com.mebigfatguy.fbcontrib.utils.SignatureUtils;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.ba.ClassContext;

/** looks for methods that catch checked exceptions, and throw unchecked
 * exceptions in their place. There are several levels of concern. Least
 * important are methods constrained by interface or super class contracts
 * not to throw checked exceptions but appear owned by the same author. Next
 * are methods constrained by interface or super class contracts and throw other
 * types of checked exceptions. Lastly are method not constrained by any interface
 * or superclass contract.
 */
public class ExceptionSoftening extends BytecodeScanningDetector 
{
	private static JavaClass runtimeClass;
	static {
		try {
			runtimeClass = Repository.lookupClass("java/lang/RuntimeException");
		} catch (ClassNotFoundException cnfe) {
			runtimeClass = null;
		}
	}
	private final BugReporter bugReporter;
	private OpcodeStack stack;
	private Map<Integer, CodeException> catchHandlerPCs;
	private List<CatchInfo> catchInfos;
	private LocalVariableTable lvt;
	private Map<String, Set<String>> constrainingInfo;
	private boolean isBooleanMethod;
	private boolean hasValidFalseReturn;
	private int catchFalseReturnPC;

	
    /** constructs a EXS detector given the reporter to report bugs on.

     * @param bugReporter the sync of bug reports
     */		
	public ExceptionSoftening(BugReporter bugReporter) {
		this.bugReporter = bugReporter;
	}
	
	/** overrides the visitor to reset the stack
	 * 
	 * @param classContext the context object of the currently parsed class
	 */
	@Override
	public void visitClassContext(ClassContext classContext) {
		try {
			if (runtimeClass != null) {
				stack = new OpcodeStack();
				super.visitClassContext(classContext);
			}
		} finally {
			stack = null;
		}
	}
		
	/** overrides the visitor to look for methods that catch checked exceptions
	 * and rethrow runtime exceptions
	 * 
	 * @param obj the context object of the currently parsed code block
	 */
	@Override
	public void visitCode(Code obj) {
		try {
			Method method = getMethod();
			isBooleanMethod = Type.BOOLEAN.equals(method.getReturnType());
			if (isBooleanMethod || prescreen(method)) {
				catchHandlerPCs = collectExceptions(obj.getExceptionTable());
				if (!catchHandlerPCs.isEmpty()) {
					stack.resetForMethodEntry(this);
					catchInfos = new ArrayList<CatchInfo>();
					lvt = method.getLocalVariableTable();
					constrainingInfo = null;
					hasValidFalseReturn = false;
					catchFalseReturnPC = -1;
					super.visitCode(obj);
					
					if (!hasValidFalseReturn && (catchFalseReturnPC >= 0) && !method.getName().startsWith("is")) {
						bugReporter.reportBug(new BugInstance(this, BugType.EXS_EXCEPTION_SOFTENING_RETURN_FALSE.name(), NORMAL_PRIORITY)
{'fraction_non_alphanumeric': 0.08240370448326668, 'fraction_numerical': 0.005472532098505577, 'mean_word_length': 4.493063583815029, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3832996', 'n_tokens_mistral': 2955, 'n_tokens_neox': 2668, 'n_words': 870}