[Fb-contrib-commit] SF.net SVN: fb-contrib:[1663] trunk/fb-contrib
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2011-04-26 01:56:00
|
Revision: 1663
http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=1663&view=rev
Author: dbrosius
Date: 2011-04-26 01:55:51 +0000 (Tue, 26 Apr 2011)
Log Message:
-----------
don't report OCP for parameters that are returned
Modified Paths:
--------------
trunk/fb-contrib/samples/OCP_Sample.java
trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/OverlyConcreteParameter.java
Modified: trunk/fb-contrib/samples/OCP_Sample.java
===================================================================
--- trunk/fb-contrib/samples/OCP_Sample.java 2011-04-22 05:14:32 UTC (rev 1662)
+++ trunk/fb-contrib/samples/OCP_Sample.java 2011-04-26 01:55:51 UTC (rev 1663)
@@ -24,81 +24,87 @@
{
public String getDisplay(HashSet<String> s, String a, String b)
{
- if (s.contains(a))
+ if (s.contains(a)) {
s.add(b);
- else
+ } else {
s.add(a + b);
-
+ }
+
StringBuffer sb = new StringBuffer();
Iterator<String> it = s.iterator();
- while (it.hasNext())
+ while (it.hasNext()) {
sb.append(it.next());
+ }
return sb.toString();
}
-
+
public void parse(DefaultHandler dh, File f)
throws SAXException, ParserConfigurationException, IOException
{
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
-
+
xr.setContentHandler( dh );
xr.parse(new InputSource( new FileInputStream(f)));
}
-
+
public void falsePositive(B b)
{
b.test();
b.x = 4;
}
-
+
+ public Color fpGetColor(Color c) {
+ return c;
+ }
+
public static interface A
{
public void test();
-
+
public void fp() throws IOException;
}
-
+
public static class B implements A
{
public int x = 0;
-
- public void test()
+
+ public void test()
{
-
+
}
-
+
public void fp()
{
-
+
}
}
-
+
public void actionPerformed(ActionEvent ae)
{
-
+
}
-
+
public void ocpFalseFPDueToExceptionSig(B b)
{
b.fp();
}
-
+
@Override
public void usesOCP(LinkedList<String> ll)
{
ll.add("foo");
}
-
+
public void testFPaastore(Color c)
{
Color[] cc = new Color[] { c, c };
}
-
+
private void readObject(ObjectInputStream ois)
{
-
+
}
}
Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/OverlyConcreteParameter.java
===================================================================
--- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/OverlyConcreteParameter.java 2011-04-22 05:14:32 UTC (rev 1662)
+++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/OverlyConcreteParameter.java 2011-04-26 01:55:51 UTC (rev 1663)
@@ -1,17 +1,17 @@
/*
* fb-contrib - Auxiliary detectors for Java programs
* Copyright (C) 2005-2011 Dave Brosius
- *
+ *
* 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
@@ -61,7 +61,7 @@
private int parmCount;
private boolean methodSignatureIsConstrained;
private boolean methodIsStatic;
-
+
/**
* constructs a OCP detector given the reporter to report bugs on
* @param bugReporter the sync of bug reports
@@ -75,7 +75,7 @@
objectClass = null;
}
}
-
+
@Override
public void visitClassContext(ClassContext classContext) {
try {
@@ -97,21 +97,21 @@
stack = null;
}
}
-
+
@Override
public void visitMethod(Method obj) {
methodSignatureIsConstrained = false;
String methodName = obj.getName();
-
+
if (!"<init>".equals(methodName)
&& !"<clinit>".equals(methodName)) {
String methodSig = obj.getSignature();
-
+
methodSignatureIsConstrained = methodIsSpecial(methodName, methodSig);
if (!methodSignatureIsConstrained) {
String parms = methodSig.split("\\(|\\)")[1];
if (parms.indexOf(';') >= 0) {
-
+
outer:for (JavaClass cls : constrainingClasses) {
Method[] methods = cls.getMethods();
for (Method m : methods) {
@@ -127,29 +127,33 @@
}
}
}
-
+
@Override
public void visitCode(final Code obj) {
try {
- if (methodSignatureIsConstrained)
+ if (methodSignatureIsConstrained) {
return;
-
- if (obj.getCode() == null)
+ }
+
+ if (obj.getCode() == null) {
return;
+ }
Method m = getMethod();
- if (m.getName().startsWith("access$"))
+ if (m.getName().startsWith("access$")) {
return;
-
+ }
+
methodIsStatic = m.isStatic();
parmCount = m.getArgumentTypes().length;
-
- if (parmCount == 0)
+
+ if (parmCount == 0) {
return;
-
+ }
+
parameterDefiners.clear();
usedParameters.clear();
stack.resetForMethodEntry(this);
-
+
if (buildParameterDefiners()) {
super.visitCode(obj);
reportBugs();
@@ -158,15 +162,16 @@
bugReporter.reportMissingClass(cnfe);
}
}
-
+
@Override
public void sawOpcode(final int seen) {
- if (parameterDefiners.isEmpty())
+ if (parameterDefiners.isEmpty()) {
return;
-
+ }
+
try {
stack.mergeJumps(this);
-
+
if ((seen == INVOKEVIRTUAL) || (seen == INVOKESTATIC) || (seen == INVOKESPECIAL) || (seen == INVOKEINTERFACE)) {
String methodSig = getSigConstantOperand();
Type[] parmTypes = Type.getArgumentTypes(methodSig);
@@ -184,8 +189,9 @@
OpcodeStack.Item itm = stack.getStackItem(parmTypes.length);
int reg = itm.getRegisterNumber();
int parm = reg;
- if (!methodIsStatic)
+ if (!methodIsStatic) {
parm--;
+ }
if ((parm >= 0) && (parm < parmCount)) {
removeUselessDefiners(reg);
}
@@ -199,68 +205,91 @@
OpcodeStack.Item itm = stack.getStackItem(0);
int reg = itm.getRegisterNumber();
int parm = reg;
- if (!methodIsStatic)
+ if (!methodIsStatic) {
parm--;
- if ((parm >= 0) && (parm < parmCount))
+ }
+ if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
+ }
} else {
parameterDefiners.clear();
}
-
+
if ((seen == GETFIELD) || (seen == PUTFIELD)) {
if (stack.getStackDepth() > 1) {
OpcodeStack.Item itm = stack.getStackItem(1);
int reg = itm.getRegisterNumber();
int parm = reg;
- if (!methodIsStatic)
+ if (!methodIsStatic) {
parm--;
- if ((parm >= 0) && (parm < parmCount))
+ }
+ if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
+ }
} else {
parameterDefiners.clear();
}
}
-
+
} else if ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) {
int reg = RegisterUtils.getALoadReg(this, seen);
int parm = reg;
- if (!methodIsStatic)
+ if (!methodIsStatic) {
parm--;
- if ((parm >= 0) && (parm < parmCount))
+ }
+ if ((parm >= 0) && (parm < parmCount)) {
usedParameters.add(Integer.valueOf(reg));
+ }
} else if (seen == AASTORE) {
- //Don't check parameters that are stored in
+ //Don't check parameters that are stored in
if (stack.getStackDepth() >= 3) {
OpcodeStack.Item itm = stack.getStackItem(0);
int reg = itm.getRegisterNumber();
int parm = reg;
- if (!methodIsStatic)
+ if (!methodIsStatic) {
parm--;
- if ((parm >= 0) && (parm < parmCount))
+ }
+ if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
+ }
} else {
parameterDefiners.clear();
}
+ } else if (seen == ARETURN) {
+ if (stack.getStackDepth() >= 1) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ int reg = item.getRegisterNumber();
+ int parm = reg;
+ if (!methodIsStatic) {
+ parm--;
+ }
+
+ if ((parm >= 0) && (parm < parmCount)) {
+ parameterDefiners.remove(Integer.valueOf(reg));
+ }
+ } else {
+ parameterDefiners.clear();
+ }
}
} finally {
stack.sawOpcode(this, seen);
}
}
-
+
private boolean methodIsSpecial(String methodName, String methodSig) {
if ("readObject".equals(methodName) && "(Ljava/io/ObjectInputStream;)V".equals(methodSig)) {
return true;
}
-
+
return false;
}
-
+
private void reportBugs() {
Iterator<Map.Entry<Integer, Map<JavaClass, List<MethodInfo>>>> it = parameterDefiners.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, Map<JavaClass, List<MethodInfo>>> entry = it.next();
-
+
Integer reg = entry.getKey();
if (!usedParameters.contains(reg)) {
it.remove();
@@ -273,14 +302,16 @@
LocalVariableTable lvt = getMethod().getLocalVariableTable();
if (lvt != null) {
LocalVariable lv = lvt.getLocalVariable(reg.intValue(), 0);
- if (lv != null)
+ if (lv != null) {
name = lv.getName();
+ }
}
int parm = reg.intValue();
- if (!methodIsStatic)
+ if (!methodIsStatic) {
parm--;
+ }
parm++; //users expect 1 based parameters
-
+
String infName = definers.keySet().iterator().next().getClassName();
bugReporter.reportBug( new BugInstance(this, "OCP_OVERLY_CONCRETE_PARAMETER", NORMAL_PRIORITY)
.addClass(this)
@@ -290,33 +321,35 @@
}
}
}
-
- /**
+
+ /**
* builds a map of method information for each method of each interface that each parameter implements of this method
* @return a map by parameter id of all the method signatures that interfaces of that parameter implements
- *
+ *
* @throws ClassNotFoundException if the class can't be loaded
*/
- private boolean buildParameterDefiners()
+ private boolean buildParameterDefiners()
throws ClassNotFoundException {
-
+
Type[] parms = getMethod().getArgumentTypes();
- if (parms.length == 0)
+ if (parms.length == 0) {
return false;
-
+ }
+
boolean hasPossiblyOverlyConcreteParm = false;
for (int i = 0; i < parms.length; i++) {
String parm = parms[i].getSignature();
if (parm.startsWith("L")) {
String clsName = parm.substring(1, parm.length() - 1).replace('/', '.');
- if (clsName.startsWith("java.lang."))
+ if (clsName.startsWith("java.lang.")) {
continue;
-
+ }
+
JavaClass cls = Repository.lookupClass(clsName);
if (cls.isClass() && (!cls.isAbstract())) {
Map<JavaClass, List<MethodInfo>> definers = getClassDefiners(cls);
-
+
if (definers.size() > 0) {
parameterDefiners.put( Integer.valueOf(i + (methodIsStatic ? 0 : 1)), definers );
hasPossiblyOverlyConcreteParm = true;
@@ -324,24 +357,25 @@
}
}
}
-
+
return hasPossiblyOverlyConcreteParm;
}
-
+
/**
* returns a map of method information for each public method for each interface this class implements
* @param cls the class whose interfaces to record
- *
+ *
* @return a map of (method name)(method sig) by interface
* @throws ClassNotFoundException if unable to load the class
*/
- private Map<JavaClass, List<MethodInfo>> getClassDefiners(final JavaClass cls)
+ private Map<JavaClass, List<MethodInfo>> getClassDefiners(final JavaClass cls)
throws ClassNotFoundException {
Map<JavaClass, List<MethodInfo>> definers = new HashMap<JavaClass, List<MethodInfo>>();
-
+
for (JavaClass ci : cls.getAllInterfaces()) {
- if ("java.lang.Comparable".equals(ci.getClassName()))
+ if ("java.lang.Comparable".equals(ci.getClassName())) {
continue;
+ }
List<MethodInfo> methodInfos = getPublicMethodInfos(ci);
if (methodInfos.size() > 0) {
definers.put(ci, methodInfos);
@@ -349,10 +383,10 @@
}
return definers;
}
-
+
/**
* returns a lost of method information of all public or protected methods in this class
- *
+ *
* @param cls the class to look for methods
* @return a map of (method name)(method signature)
*/
@@ -367,15 +401,15 @@
}
return methodInfos;
}
-
+
private void removeUselessDefiners(final int reg) {
-
+
Map<JavaClass, List<MethodInfo>> definers = parameterDefiners.get(Integer.valueOf(reg));
if ((definers != null) && (definers.size() > 0)) {
String methodSig = getSigConstantOperand();
String methodName = getNameConstantOperand();
MethodInfo methodInfo = new MethodInfo(methodName, methodSig, null);
-
+
Iterator<List<MethodInfo>> it = definers.values().iterator();
while (it.hasNext()) {
boolean methodDefined = false;
@@ -396,20 +430,21 @@
break;
}
}
- if (!methodDefined)
+ if (!methodDefined) {
it.remove();
+ }
}
if (definers.isEmpty()) {
parameterDefiners.remove(Integer.valueOf(reg));
}
}
}
-
+
/**
* returns whether this exception is handled either in a try/catch or throws clause at this pc
- *
+ *
* @param ex the name of the exception
- *
+ *
* @return whether the exception is handled
*/
private boolean isExceptionHandled(String ex) {
@@ -421,8 +456,9 @@
String[] throwClauseExNames = et.getExceptionNames();
for (String throwClauseExName : throwClauseExNames) {
JavaClass throwClauseEx = Repository.lookupClass(throwClauseExName);
- if (thrownEx.instanceOf(throwClauseEx))
+ if (thrownEx.instanceOf(throwClauseEx)) {
return true;
+ }
}
}
// Next look at the try catch blocks
@@ -435,8 +471,9 @@
if (type != 0) {
String catchExName = getConstantPool().getConstantString(type, Constants.CONSTANT_Class);
JavaClass catchException = Repository.lookupClass(catchExName);
- if (thrownEx.instanceOf(catchException))
+ if (thrownEx.instanceOf(catchException)) {
return true;
+ }
}
}
}
@@ -454,66 +491,71 @@
parameterDefiners.remove(Integer.valueOf(reg));
return;
}
-
+
Map<JavaClass, List<MethodInfo>> definers = parameterDefiners.get(Integer.valueOf(reg));
if ((definers != null) && (definers.size() > 0)) {
Iterator<JavaClass> it = definers.keySet().iterator();
while (it.hasNext()) {
JavaClass definer = it.next();
- if (!definer.getClassName().equals(parmSig))
+ if (!definer.getClassName().equals(parmSig)) {
it.remove();
+ }
}
-
- if (definers.isEmpty())
+
+ if (definers.isEmpty()) {
parameterDefiners.remove(Integer.valueOf(reg));
+ }
}
}
}
-
+
public static class MethodInfo
{
private final String methodName;
private final String methodSig;
private final String[] methodExceptions;
-
+
public MethodInfo(String name, String sig, String[] excs) {
methodName = name;
methodSig = sig;
methodExceptions = excs;
}
-
+
public String getMethodName() {
return methodName;
}
-
+
public String getMethodSignature() {
return methodSig;
}
-
+
public String[] getMethodExceptions() {
return methodExceptions;
}
-
+
@Override
public int hashCode() {
return methodName.hashCode() ^ methodSig.hashCode();
}
-
+
@Override
public boolean equals(Object o) {
- if (!(o instanceof MethodInfo))
+ if (!(o instanceof MethodInfo)) {
return false;
-
+ }
+
MethodInfo that = (MethodInfo)o;
-
- if (!methodName.equals(that.methodName))
+
+ if (!methodName.equals(that.methodName)) {
return false;
- if (!methodSig.equals(that.methodSig))
+ }
+ if (!methodSig.equals(that.methodSig)) {
return false;
-
+ }
+
return true;
}
-
+
@Override
public String toString() {
return methodName + methodSig;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|