[Fb-contrib-commit] SF.net SVN: fb-contrib:[1489] trunk/fb-contrib
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2010-01-18 16:54:15
|
Revision: 1489
http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=1489&view=rev
Author: dbrosius
Date: 2010-01-18 16:54:08 +0000 (Mon, 18 Jan 2010)
Log Message:
-----------
new detector - just starting - ROOM
Modified Paths:
--------------
trunk/fb-contrib/etc/findbugs.xml
trunk/fb-contrib/etc/messages.xml
Added Paths:
-----------
trunk/fb-contrib/samples/ROOM_Sample.java
trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ReflectionOnObjectMethods.java
Modified: trunk/fb-contrib/etc/findbugs.xml
===================================================================
--- trunk/fb-contrib/etc/findbugs.xml 2010-01-15 05:46:10 UTC (rev 1488)
+++ trunk/fb-contrib/etc/findbugs.xml 2010-01-18 16:54:08 UTC (rev 1489)
@@ -320,6 +320,10 @@
speed="fast"
reports="MDM_RUNTIME_EXIT_OR_HALT,MDM_RUNFINALIZATION,EQ_BIGDECIMAL_EQUALS,MDM_INETADDRESS_GETLOCALHOST,MDM_PROMISCUOUS_SERVERSOCKET,MDM_RANDOM_SEED,MDM_SECURERANDOM_CTOR,MDM_SECURERANDOM_GETSEED,MDM_THREAD_PRIORITIES,MDM_THREAD_YIELD,MDM_WAIT_WITHOUT_TIMEOUT,MDM_THREAD_FAIRNESS,MDM_REENTRANTLOCK_HELDBY,MDM_STRING_BYTES_ENCODING,MDM_SETDEFAULTLOCALE" />
+ <Detector class="com.mebigfatguy.fbcontrib.detect.ReflectionOnObjectMethods"
+ speed="fast"
+ reports="ROOM_REFLECTION_ON_OBJECT_METHODS" />
+
<!-- BugPattern -->
<BugPattern abbrev="ISB" type="ISB_INEFFICIENT_STRING_BUFFERING"
@@ -555,53 +559,55 @@
<BugPattern abbrev="ITU" type="ITU_INAPPROPRIATE_TOSTRING_USE"
category="CORRECTNESS" />
<BugPattern abbrev="IKNC" type="IKNC_INCONSISTENT_HTTP_ATTRIBUTE_CASING"
- category="STYLE" experimental="true" />
+ category="STYLE" />
<BugPattern abbrev="IKNC" type="IKNC_INCONSISTENT_HTTP_PARAM_CASING"
- category="STYLE" experimental="true" />
+ category="STYLE" />
<BugPattern abbrev="OC" type="OC_OVERZEALOUS_CASTING"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="PDP" type="PDP_POORLY_DEFINED_PARAMETER"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="NSE" type="NSE_NON_SYMMETRIC_EQUALS"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="CVAA" type="CVAA_CONTRAVARIANT_ARRAY_ASSIGNMENT"
category="CORRECTNESS" experimental="true" />
<BugPattern abbrev="CVAA" type="CVAA_CONTRAVARIANT_ELEMENT_ASSIGNMENT"
category="CORRECTNESS" experimental="true" />
<BugPattern abbrev="NFF" type="NFF_NON_FUNCTIONAL_FIELD"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="SNG" type="SNG_SUSPICIOUS_NULL_FIELD_GUARD"
category="CORRECTNESS" experimental="true" />
<BugPattern abbrev="SNG" type="SNG_SUSPICIOUS_NULL_LOCAL_GUARD"
category="CORRECTNESS" experimental="true" />
<BugPattern abbrev="MDM" type="MDM_RUNTIME_EXIT_OR_HALT"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_RUNFINALIZATION"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_INETADDRESS_GETLOCALHOST"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_PROMISCUOUS_SERVERSOCKET"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_THREAD_PRIORITIES"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_THREAD_YIELD"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_WAIT_WITHOUT_TIMEOUT"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_SIGNAL_NOT_SIGNALALL"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_THREAD_FAIRNESS"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_LOCK_ISLOCKED"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_STRING_BYTES_ENCODING"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_SETDEFAULTLOCALE"
- category="MT_CORRECTNESS" experimental="true" />
+ category="MT_CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_BIGDECIMAL_EQUALS"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_RANDOM_SEED"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
<BugPattern abbrev="MDM" type="MDM_SECURERANDOM"
- category="CORRECTNESS" experimental="true" />
+ category="CORRECTNESS" />
+ <BugPattern abbrev="ROOM" type="ROOM_REFLECTION_ON_OBJECT_METHODS"
+ category="CORRECTNESS" />
</FindbugsPlugin>
\ No newline at end of file
Modified: trunk/fb-contrib/etc/messages.xml
===================================================================
--- trunk/fb-contrib/etc/messages.xml 2010-01-15 05:46:10 UTC (rev 1488)
+++ trunk/fb-contrib/etc/messages.xml 2010-01-18 16:54:08 UTC (rev 1489)
@@ -453,7 +453,7 @@
</Details>
</Detector>
- <Detector class="com.mebigfatguy.fbcontrib.detect.DateComparison">
+ <Detector class="com.mebigfatguy.fbcontrib.detect.DateComparison">
<Details>
<![CDATA[
<p> Looks for inefficient comparison of Date objects using two comparisons when one would do.</p>
@@ -1099,6 +1099,17 @@
]]>
</Details>
</Detector>
+
+ <Detector class="com.mebigfatguy.fbcontrib.detect.ReflectionOnObjectMethods">
+ <Details>
+ <![CDATA[
+ <p>This detector looks for reflective calls on methods that are found java.lang.Object.
+ As these methods are always available, there is no reason to use reflection to call them.
+ </p>
+ <p>It is a fast detector</p>
+ ]]>
+ </Details>
+ </Detector>
<!-- BugPattern -->
@@ -2996,6 +3007,18 @@
]]>
</Details>
</BugPattern>
+
+ <BugPattern type="ROOM_REFLECTION_ON_OBJECT_METHODS">
+ <ShortDescription>Method uses reflection to call a method available on java.lang.Object</ShortDescription>
+ <LongDescription>Method {1} uses reflection to call a method available on java.lang.Object</LongDescription>
+ <Details>
+ <![CDATA[
+ <p>This method uses reflection to call a method that is defined in java.lang.Object.
+ As these methods are always available, it is not necessary to call these methods with
+ reflection.
+ ]]>
+ </Details>
+ </BugPattern>
<!-- BugCode -->
@@ -3089,4 +3112,5 @@
<BugCode abbrev="NFF">Non Functional Field</BugCode>
<BugCode abbrev="SNG">SUSPICIOUS Null Guard</BugCode>
<BugCode abbrev="MDM">More Dumb Methods</BugCode>
+ <BugCode abbrev="ROOM">Reflection on Object Methods</BugCode>
</MessageCollection>
Added: trunk/fb-contrib/samples/ROOM_Sample.java
===================================================================
--- trunk/fb-contrib/samples/ROOM_Sample.java (rev 0)
+++ trunk/fb-contrib/samples/ROOM_Sample.java 2010-01-18 16:54:08 UTC (rev 1489)
@@ -0,0 +1,13 @@
+import java.lang.reflect.Method;
+
+
+public class ROOM_Sample
+{
+ public void testRoomWithLocals() throws Exception
+ {
+ Class c = Class.forName("java.lang.Object");
+ Method m = c.getMethod("equals", Object.class);
+
+ String s = (String)m.invoke(this, new ROOM_Sample());
+ }
+}
Property changes on: trunk/fb-contrib/samples/ROOM_Sample.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ReflectionOnObjectMethods.java
===================================================================
--- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ReflectionOnObjectMethods.java (rev 0)
+++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ReflectionOnObjectMethods.java 2010-01-18 16:54:08 UTC (rev 1489)
@@ -0,0 +1,202 @@
+package com.mebigfatguy.fbcontrib.detect;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.bcel.classfile.Code;
+
+import com.mebigfatguy.fbcontrib.utils.RegisterUtils;
+
+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 method calls through reflection on methods found in
+ * java.lang.Object. As these methods are always available, there's no
+ * reason to do this.
+ */
+public class ReflectionOnObjectMethods extends BytecodeScanningDetector {
+
+ private static final Set<String> objectSigs = new HashSet<String>();
+ static {
+ objectSigs.add("clone()");
+ objectSigs.add("equals(Ljava/lang/Object;)");
+ objectSigs.add("finalize()");
+ objectSigs.add("getClass()");
+ objectSigs.add("hashCode()");
+ objectSigs.add("notify()");
+ objectSigs.add("notifyAll()");
+ objectSigs.add("toString()");
+ objectSigs.add("wait");
+ objectSigs.add("wait(J)");
+ objectSigs.add("wait(JI");
+
+
+ }
+ private BugReporter bugReporter;
+ private OpcodeStack stack;
+ private Map<Integer, String[]> localClassTypes;
+
+ public ReflectionOnObjectMethods(BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ }
+
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ try {
+ stack = new OpcodeStack();
+ localClassTypes = new HashMap<Integer, String[]>();
+ super.visitClassContext(classContext);
+ } finally {
+ stack = null;
+ localClassTypes = null;
+ }
+ }
+
+ @Override
+ public void visitCode(Code obj) {
+ stack.resetForMethodEntry(this);
+ localClassTypes.clear();
+ super.visitCode(obj);
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ Integer arraySize = null;
+ String[] loadedTypes = null;
+
+ try {
+ switch (seen) {
+ case ANEWARRAY: {
+ if ("java/lang/Class".equals(getClassConstantOperand())) {
+ if (stack.getStackDepth() >= 1) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ arraySize = (Integer)item.getConstant();
+ }
+ }
+ }
+ break;
+
+ case AASTORE: {
+ if (stack.getStackDepth() >= 3) {
+ OpcodeStack.Item arrayItem = stack.getStackItem(2);
+ String[] arrayTypes = (String[])arrayItem.getUserValue();
+ if (arrayTypes != null) {
+ OpcodeStack.Item valueItem = stack.getStackItem(0);
+ String type = (String)valueItem.getConstant();
+ if (type != null) {
+ OpcodeStack.Item indexItem = stack.getStackItem(1);
+ Integer index = (Integer)indexItem.getConstant();
+ if (index != null) {
+ arrayTypes[index.intValue()] = type;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3:
+ case ASTORE: {
+ if (stack.getStackDepth() >= 1) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ String[] arrayTypes = (String[])item.getUserValue();
+ if (arrayTypes != null) {
+ int reg = RegisterUtils.getAStoreReg(this, seen);
+ localClassTypes.put(Integer.valueOf(reg), arrayTypes);
+ }
+ }
+ }
+ break;
+
+ case ALOAD_0:
+ case ALOAD_1:
+ case ALOAD_2:
+ case ALOAD_3:
+ case ALOAD: {
+ int reg = RegisterUtils.getAStoreReg(this, seen);
+ loadedTypes = localClassTypes.get(Integer.valueOf(reg));
+ }
+ break;
+
+ case INVOKEVIRTUAL: {
+ String cls = getClassConstantOperand();
+ if ("java/lang/Class".equals(cls)) {
+ String method = getNameConstantOperand();
+ if ("getMethod".equals(method)) {
+ String sig = getSigConstantOperand();
+ if ("(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".equals(sig)) {
+ if (stack.getStackDepth() >= 2) {
+ OpcodeStack.Item clsArgs = stack.getStackItem(0);
+ String[] arrayTypes = (String[])clsArgs.getUserValue();
+ if (arrayTypes != null) {
+ OpcodeStack.Item methodItem = stack.getStackItem(1);
+ String methodName = (String)methodItem.getConstant();
+ if (methodName != null) {
+ String reflectionSig = buildReflectionSignature(methodName, arrayTypes);
+ if (objectSigs.contains(reflectionSig)) {
+ loadedTypes = arrayTypes;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if ("java/lang/reflect/Method".equals(cls)) {
+ String method = getNameConstantOperand();
+ if ("invoke".equals(method)) {
+ if (stack.getStackDepth() >= 3) {
+ OpcodeStack.Item methodItem = stack.getStackItem(2);
+ String[] arrayTypes = (String[])methodItem.getUserValue();
+ if (arrayTypes != null) {
+ bugReporter.reportBug(new BugInstance(this, "ROOM_REFLECTION_ON_OBJECT_METHODS", NORMAL_PRIORITY)
+ .addClass(this)
+ .addMethod(this)
+ .addSourceLine(this));
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ } finally {
+ stack.sawOpcode(this, seen);
+ if (arraySize != null) {
+ if (stack.getStackDepth() >= 1) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ item.setUserValue(new String[arraySize.intValue()]);
+ }
+ } else if (loadedTypes != null) {
+ if (stack.getStackDepth() >= 1) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ item.setUserValue(loadedTypes);
+ }
+ }
+ }
+ }
+
+ private String buildReflectionSignature(String methodName, String[] parmTypes) {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append(methodName);
+ sb.append("(");
+ for (int i = 0; i < parmTypes.length; i++) {
+ sb.append("L");
+ String type = parmTypes[i];
+ sb.append(type);
+ if ((type.length() > 1) || ("IJ".indexOf(type) < 0))
+ sb.append(";");
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+}
Property changes on: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ReflectionOnObjectMethods.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|