[Fb-contrib-commit] SF.net SVN: fb-contrib:[1825] trunk/fb-contrib
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2017-09-04 17:52:11
|
Revision: 1825
http://sourceforge.net/p/fb-contrib/code/1825
Author: dbrosius
Date: 2017-09-04 17:52:07 +0000 (Mon, 04 Sep 2017)
Log Message:
-----------
sync from github
Modified Paths:
--------------
trunk/fb-contrib/build.xml
trunk/fb-contrib/etc/findbugs.xml
trunk/fb-contrib/etc/samples.fbp
trunk/fb-contrib/htdocs/index.shtml
trunk/fb-contrib/htdocs/repository.html
trunk/fb-contrib/pom.xml
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ContainsBasedConditional.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ListIndexedIterating.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LiteralStringComparison.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LostExceptionStackTrace.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/NonRecycleableTaglibs.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PoorlyDefinedParameter.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PossiblyRedundantMethodCalls.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PresizeCollections.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/SuspiciousUninitializedArray.java
trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/utils/ToString.java
trunk/fb-contrib/src/samples/java/ex/COM_Sample.java
trunk/fb-contrib/src/samples/java/ex/LEST_Sample.java
trunk/fb-contrib/src/samples/java/ex/LII_Sample.java
trunk/fb-contrib/src/samples/java/ex/PDP_Sample.java
trunk/fb-contrib/src/samples/java/ex/PSC_Sample.java
trunk/fb-contrib/src/samples/java/ex/SEO_Sample.java
trunk/fb-contrib/src/samples/java/ex/SUA_Sample.java
Modified: trunk/fb-contrib/build.xml
===================================================================
--- trunk/fb-contrib/build.xml 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/build.xml 2017-09-04 17:52:07 UTC (rev 1825)
@@ -31,7 +31,7 @@
<property name="javac.debug" value="on" />
<property name="test_reports.dir" value="${target.dir}/reports/test"/>
- <property name="fb-contrib.version" value="7.0.3" />
+ <property name="fb-contrib.version" value="7.0.4" />
<property name="sonatype.dir" value="${user.home}/.fb-contrib-${fb-contrib.version}-sonatype" />
Modified: trunk/fb-contrib/etc/findbugs.xml
===================================================================
--- trunk/fb-contrib/etc/findbugs.xml 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/etc/findbugs.xml 2017-09-04 17:52:07 UTC (rev 1825)
@@ -20,7 +20,7 @@
<!-- Detectors -->
-<!-- COMMENT OUT FOR RELEASE
+<!-- COMMENT OUT FOR RELEASE
<Detector class="com.mebigfatguy.fbcontrib.debug.OCSDebugger" speed="fast"/>
@@ -318,6 +318,7 @@
<Detector class="com.mebigfatguy.fbcontrib.detect.UseTryWithResources" speed="fast" reports="UTWR_USE_TRY_WITH_RESOURCES"/>
<Detector class="com.mebigfatguy.fbcontrib.detect.ReflectionIssues" speed="fast" reports="RFI_SET_ACCESSIBLE"/>
+
COMMENT OUT FOR POINT RELEASE -->
<!-- BugPattern -->
Modified: trunk/fb-contrib/etc/samples.fbp
===================================================================
--- trunk/fb-contrib/etc/samples.fbp 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/etc/samples.fbp 2017-09-04 17:52:07 UTC (rev 1825)
@@ -1,30 +1,30 @@
<Project projectName="sample">
- <Jar>././././../target/classes/samples</Jar>
- <AuxClasspathEntry>././././../lib/asm-debug-all-5.0.2.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/backport-util-concurrent-3.1.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/commons-codec-1.10.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/commons-collections-3.2.2.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/commons-lang3-3.4.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/guava-19.0.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/httpclient-4.5.2.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/httpclient-cache-4.5.2.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/httpcore-4.4.5.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/javax.persistence-2.1.1.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/javax.servlet-api-3.1.0.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/javax.servlet.jsp-api-2.3.1.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/junit-4.12.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/log4j-1.2.17.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/slf4j-api-1.7.21.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/spring-beans-4.3.3.RELEASE.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/spring-context-4.3.3.RELEASE.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/spring-tx-4.3.3.RELEASE.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/threetenbp-1.3.2.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/jena-shaded-guava-3.1.0.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/commons-io-2.4.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././././../lib/testng-6.9.10.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././../lib/javax.ws.rs-api-2.0.1.jar</AuxClasspathEntry>
- <AuxClasspathEntry>././../lib/jersey-media-multipart-2.25.1.jar</AuxClasspathEntry>
- <AuxClasspathEntry>./../lib/mockito-core-2.8.47.jar</AuxClasspathEntry>
+ <Jar>../target/classes/samples</Jar>
+ <AuxClasspathEntry>../lib/asm-debug-all-5.0.2.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/backport-util-concurrent-3.1.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/commons-codec-1.10.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/commons-collections-3.2.2.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/commons-lang3-3.4.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/guava-19.0.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/httpclient-4.5.2.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/httpclient-cache-4.5.2.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/httpcore-4.4.5.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/javax.persistence-2.1.1.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/javax.servlet-api-3.1.0.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/javax.servlet.jsp-api-2.3.1.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/junit-4.12.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/log4j-1.2.17.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/slf4j-api-1.7.21.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/spring-beans-4.3.3.RELEASE.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/spring-context-4.3.3.RELEASE.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/spring-tx-4.3.3.RELEASE.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/threetenbp-1.3.2.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/jena-shaded-guava-3.1.0.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/commons-io-2.4.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/testng-6.9.10.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/javax.ws.rs-api-2.0.1.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/jersey-media-multipart-2.25.1.jar</AuxClasspathEntry>
+ <AuxClasspathEntry>../lib/mockito-core-2.8.47.jar</AuxClasspathEntry>
<AuxClasspathEntry>../lib/hamcrest-core-1.3.jar</AuxClasspathEntry>
- <SrcDir>./././../src/samples/java</SrcDir>
+ <SrcDir>../src/samples/java</SrcDir>
</Project>
Modified: trunk/fb-contrib/htdocs/index.shtml
===================================================================
--- trunk/fb-contrib/htdocs/index.shtml 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/htdocs/index.shtml 2017-09-04 17:52:07 UTC (rev 1825)
@@ -68,7 +68,7 @@
</li>
</ul>
</p>
- <p style="font-weight: bold;">The latest version of fb-contrib is 7.0.3 available for download
+ <p style="font-weight: bold;">The latest version of fb-contrib is 7.0.4 available for download
<a href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22fb-contrib%22">here</a>.</p>
<p style="font-weight: bold;">This version requires FindBugs 3.0.1 or better</p>
<p style="font-weight: bold;">Please note that active development for this project is now done on
Modified: trunk/fb-contrib/htdocs/repository.html
===================================================================
--- trunk/fb-contrib/htdocs/repository.html 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/htdocs/repository.html 2017-09-04 17:52:07 UTC (rev 1825)
@@ -22,7 +22,7 @@
<table style="margin-left: 40px; background-color: #A0A0FF; padding: 20px; border-width: 1px; border-style: outset; border-color: #000000;">
<tr><td><b>GroupId:</b></td><td>com.mebigfatguy.fb-contrib</td></tr>
<tr><td><b>ArtifactId:</b></td><td>fb-contrib</td></tr>
- <tr><td><b>Version:</b></td><td>7.0.3</td></tr>
+ <tr><td><b>Version:</b></td><td>7.0.4 or 7.0.4.sb</td></tr>
</table>
</div>
Modified: trunk/fb-contrib/pom.xml
===================================================================
--- trunk/fb-contrib/pom.xml 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/pom.xml 2017-09-04 17:52:07 UTC (rev 1825)
@@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.mebigfatguy.fb-contrib</groupId>
<artifactId>fb-contrib</artifactId>
- <version>7.0.3</version>
+ <version>7.0.4</version>
<!-- TODO: Delete this and replace with enforcer plugin. This is for maven plugins only! Latest maven will through warnings. -->
<prerequisites>
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -249,6 +249,7 @@
for (int offset : offsets) {
casePositions.set(pc + offset);
}
+ casePositions.set(pc + getDefaultSwitchOffset());
}
} finally {
stack.sawOpcode(this, seen);
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ContainsBasedConditional.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ContainsBasedConditional.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ContainsBasedConditional.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -18,8 +18,7 @@
*/
package com.mebigfatguy.fbcontrib.detect;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.BitSet;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.Constant;
@@ -54,7 +53,7 @@
private BugReporter bugReporter;
private OpcodeStack stack;
- private List<Integer> switchLocs;
+ private BitSet switchLocs;
private State state;
private int loadType;
private String constType;
@@ -75,7 +74,7 @@
public void visitClassContext(ClassContext classContext) {
try {
stack = new OpcodeStack();
- switchLocs = new ArrayList<Integer>();
+ switchLocs = new BitSet();
super.visitClassContext(classContext);
} finally {
switchLocs = null;
@@ -101,17 +100,18 @@
try {
stack.precomputation(this);
+ int pc = getPC();
if ((seen == LOOKUPSWITCH) || (seen == TABLESWITCH)) {
- switchLocs.add(Integer.valueOf(getPC()));
+ switchLocs.set(pc);
for (int offset : getSwitchOffsets()) {
- switchLocs.add(Integer.valueOf(getPC() + offset));
+ switchLocs.set(pc + offset);
}
+ switchLocs.set(pc + getDefaultSwitchOffset());
}
- if (!switchLocs.isEmpty() && (getPC() == switchLocs.get(0).intValue())) {
+ if (switchLocs.get(pc)) {
state = State.SAW_NOTHING;
- switchLocs.remove(0);
- return;
+ switchLocs.clear(pc);
}
switch (state) {
@@ -128,7 +128,7 @@
}
} else {
loadType = seen;
- bugPC = getPC();
+ bugPC = pc;
state = State.SAW_LOAD;
}
} else {
@@ -175,7 +175,8 @@
break;
case SAW_CONST:
- if ((seen == INVOKEVIRTUAL) && "equals".equals(getNameConstantOperand()) && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(getSigConstantOperand())) {
+ if ((seen == INVOKEVIRTUAL) && "equals".equals(getNameConstantOperand())
+ && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(getSigConstantOperand())) {
state = State.SAW_EQUALS;
} else if (seen == IF_ICMPEQ) {
conditionCount++;
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -33,6 +33,7 @@
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.LDC;
+import org.apache.bcel.generic.LDC2_W;
import org.apache.bcel.generic.ReferenceType;
import org.apache.bcel.generic.Type;
@@ -144,6 +145,10 @@
return;
}
+ if ((getMethod().getAccessFlags() & ACC_SYNCHRONIZED) != (superCode.getAccess() & ACC_SYNCHRONIZED)) {
+ return;
+ }
+
parmTypes = getMethod().getArgumentTypes();
nextParmIndex = 0;
nextParmOffset = getMethod().isStatic() ? 0 : 1;
@@ -248,7 +253,7 @@
* @return whether the access modifiers are the same
*/
private static boolean sameAccess(int parentAccess, int childAccess) {
- return ((parentAccess & (Constants.ACC_PUBLIC | Constants.ACC_PROTECTED)) == (childAccess & (Constants.ACC_PUBLIC | Constants.ACC_PROTECTED)));
+ return ((parentAccess & (Constants.ACC_PUBLIC | Constants.ACC_PROTECTED)) == ((childAccess & (Constants.ACC_PUBLIC | Constants.ACC_PROTECTED))));
}
/**
@@ -351,6 +356,20 @@
return false;
}
// TODO: Other Constant types
+ } else if (childin instanceof LDC2_W) {
+ Type childType = ((LDC2_W) childin).getType(childPoolGen);
+ Type parentType = ((LDC2_W) parentin).getType(parentPoolGen);
+ if (!childType.equals(parentType)) {
+ return false;
+ }
+
+ Object childValue = ((LDC2_W) childin).getValue(childPoolGen);
+ Object parentValue = ((LDC2_W) parentin).getValue(parentPoolGen);
+
+ if (!childValue.equals(parentValue)) {
+ return false;
+ }
+
} else {
if (!childin.equals(parentin)) {
return false;
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ListIndexedIterating.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ListIndexedIterating.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/ListIndexedIterating.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -406,16 +406,24 @@
return true;
}
} else {
+ XField newField = itm.getXField();
+ if (newField == null) {
+ return true;
+ }
+
XField seenField = loopCollectionItem.getXField();
- if (seenField != null) {
- if (itm.getRegisterNumber() >= 0) {
- return true;
- }
- XField newField = itm.getXField();
- if ((newField != null) && (!newField.getName().equals(seenField.getName()))) {
- return true;
- }
+ if (seenField == null) {
+ return true;
}
+
+ if (itm.getRegisterNumber() >= 0) {
+ return true;
+ }
+
+ if ((loopCollectionItem.getFieldLoadedFromRegister() != itm.getFieldLoadedFromRegister()) || (itm.getFieldLoadedFromRegister() == -1)
+ || (!newField.getName().equals(seenField.getName()))) {
+ return true;
+ }
}
loopCollectionItem = itm;
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LiteralStringComparison.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LiteralStringComparison.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LiteralStringComparison.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -75,7 +75,7 @@
public void visitClassContext(ClassContext classContext) {
try {
stack = new OpcodeStack();
- lookupSwitches = new ArrayList<LookupDetails>();
+ lookupSwitches = new ArrayList<>();
super.visitClassContext(classContext);
} finally {
stack = null;
@@ -173,6 +173,7 @@
for (int offset : offsets) {
bs.set(pc + offset);
}
+ bs.set(pc + getDefaultSwitchOffset());
lookupSwitches.add(new LookupDetails(stringRef, bs));
}
}
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LostExceptionStackTrace.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LostExceptionStackTrace.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/LostExceptionStackTrace.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -264,6 +264,10 @@
break;
}
}
+ if (catchInfo.getFinish() == Integer.MAX_VALUE) {
+ catchInfo.setFinish(pc);
+ }
+
} else if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) {
if (lastWasExitPoint) {
// crazy jdk6 finally block injection -- shut
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/NonRecycleableTaglibs.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/NonRecycleableTaglibs.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/NonRecycleableTaglibs.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -28,6 +28,7 @@
import org.apache.bcel.classfile.Method;
import com.mebigfatguy.fbcontrib.utils.BugType;
+import com.mebigfatguy.fbcontrib.utils.QMethod;
import com.mebigfatguy.fbcontrib.utils.SignatureUtils;
import com.mebigfatguy.fbcontrib.utils.UnmodifiableSet;
import com.mebigfatguy.fbcontrib.utils.Values;
@@ -55,11 +56,11 @@
/**
* methodname:methodsig to type of setter methods
*/
- private Map<String, String> attributes;
+ private Map<QMethod, String> attributes;
/**
- * methodname:methodsig to (fieldname:fieldtype)s
+ * QMethod to (fieldname:fieldtype)s
*/
- private Map<String, Map<String, SourceLineAnnotation>> methodWrites;
+ private Map<QMethod, Map<String, SourceLineAnnotation>> methodWrites;
private Map<String, FieldAnnotation> fieldAnnotations;
/**
@@ -113,8 +114,8 @@
* the class to look for setter methods to infer properties
* @return the map of possible attributes/types
*/
- private static Map<String, String> getAttributes(JavaClass cls) {
- Map<String, String> atts = new HashMap<>();
+ private static Map<QMethod, String> getAttributes(JavaClass cls) {
+ Map<QMethod, String> atts = new HashMap<>();
Method[] methods = cls.getMethods();
for (Method m : methods) {
String name = m.getName();
@@ -126,7 +127,7 @@
if (validAttrTypes.contains(parmSig)) {
Code code = m.getCode();
if ((code != null) && (code.getCode().length < MAX_ATTRIBUTE_CODE_LENGTH)) {
- atts.put(name + ':' + sig, parmSig);
+ atts.put(new QMethod(name, sig), parmSig);
}
}
}
@@ -158,7 +159,7 @@
@Override
public void sawOpcode(int seen) {
if (seen == PUTFIELD) {
- String methodInfo = getMethodName() + ':' + getMethodSig();
+ QMethod methodInfo = new QMethod(getMethodName(), getMethodSig());
Map<String, SourceLineAnnotation> fields = methodWrites.get(methodInfo);
if (fields == null) {
fields = new HashMap<>();
@@ -177,8 +178,8 @@
* generates all the bug reports for attributes that are not recycleable
*/
private void reportBugs() {
- for (Map.Entry<String, String> attEntry : attributes.entrySet()) {
- String methodInfo = attEntry.getKey();
+ for (Map.Entry<QMethod, String> attEntry : attributes.entrySet()) {
+ QMethod methodInfo = attEntry.getKey();
String attType = attEntry.getValue();
Map<String, SourceLineAnnotation> fields = methodWrites.get(methodInfo);
@@ -196,7 +197,7 @@
String fieldName = fieldInfo.substring(0, colonPos);
- for (Map.Entry<String, Map<String, SourceLineAnnotation>> fwEntry : methodWrites.entrySet()) {
+ for (Map.Entry<QMethod, Map<String, SourceLineAnnotation>> fwEntry : methodWrites.entrySet()) {
if (fwEntry.getKey().equals(methodInfo)) {
continue;
}
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PoorlyDefinedParameter.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PoorlyDefinedParameter.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PoorlyDefinedParameter.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -76,6 +76,10 @@
public void visitCode(Code obj) {
try {
Method m = getMethod();
+ if (m.isSynthetic()) {
+ return;
+ }
+
if (m.isStatic() || m.isPrivate() || Values.CONSTRUCTOR.equals(m.getName())) {
parmSigs = SignatureUtils.getParameterSlotAndSignatures(m.isStatic(), m.getSignature());
if (!parmSigs.isEmpty() && prescreen(m)) {
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PossiblyRedundantMethodCalls.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PossiblyRedundantMethodCalls.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PossiblyRedundantMethodCalls.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -268,6 +268,7 @@
for (int offset : offsets) {
branchTargets.set(offset + pc);
}
+ branchTargets.set(getDefaultSwitchOffset() + pc);
} else if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) {
localMethodCalls.remove(Integer.valueOf(RegisterUtils.getAStoreReg(this, seen)));
} else if (seen == PUTFIELD) {
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PresizeCollections.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PresizeCollections.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/PresizeCollections.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -19,6 +19,7 @@
package com.mebigfatguy.fbcontrib.detect;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -26,6 +27,7 @@
import java.util.Set;
import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.CodeException;
import com.mebigfatguy.fbcontrib.utils.BugType;
import com.mebigfatguy.fbcontrib.utils.SignatureBuilder;
@@ -42,235 +44,344 @@
import edu.umd.cs.findbugs.ba.ClassContext;
/**
- * finds methods that create and populate collections, and while knowing the end size of those collections, does not pre allocate the collection to be big
- * enough. This just causes unneeded reallocations putting strain on the garbage collector.
+ * finds methods that create and populate collections, and while knowing the end
+ * size of those collections, does not pre allocate the collection to be big
+ * enough. This just causes unneeded reallocations putting strain on the garbage
+ * collector.
*/
@CustomUserValue
public class PresizeCollections extends BytecodeScanningDetector {
- private static final Set<String> PRESIZEABLE_COLLECTIONS = UnmodifiableSet.create("java/util/ArrayBlockingQueue", "java/util/ArrayDeque",
- "java/util/ArrayList", "java/util/HashMap", "java/util/HashSet", "java/util/LinkedBlockingQueue", "java/util/LinkedHashMap",
- "java/util/LinkedHashSet", "java/util/PriorityBlockingQueue", "java/util/PriorityQueue", "java/util/Vector");
+ private static final Set<String> PRESIZEABLE_COLLECTIONS = UnmodifiableSet.create("java/util/ArrayBlockingQueue",
+ "java/util/ArrayDeque", "java/util/ArrayList", "java/util/HashMap", "java/util/HashSet",
+ "java/util/LinkedBlockingQueue", "java/util/LinkedHashMap", "java/util/LinkedHashSet",
+ "java/util/PriorityBlockingQueue", "java/util/PriorityQueue", "java/util/Vector");
- private BugReporter bugReporter;
- private OpcodeStack stack;
- private int allocNumber;
- private Map<Integer, Integer> allocLocation;
- private Map<Integer, List<Integer>> allocToAddPCs;
- private List<DownBranch> downBranches;
+ private BugReporter bugReporter;
+ private OpcodeStack stack;
+ private int nextAllocNumber;
+ private Map<Comparable<?>, Integer> storeToAllocNumber;
+ private Map<Integer, Integer> allocLocation;
+ private Map<Integer, List<Integer>> allocToAddPCs;
+ private List<CodeRange> optionalRanges;
- public PresizeCollections(BugReporter bugReporter) {
- this.bugReporter = bugReporter;
- }
+ public PresizeCollections(BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ }
- /**
- * overrides the visitor to initialize the opcode stack
- *
- * @param classContext
- * the context object that holds the JavaClass being parsed
- */
- @Override
- public void visitClassContext(ClassContext classContext) {
- try {
- stack = new OpcodeStack();
- allocLocation = new HashMap<>();
- allocToAddPCs = new HashMap<>();
- downBranches = new ArrayList<>();
- super.visitClassContext(classContext);
- } finally {
- stack = null;
- allocLocation = null;
- allocToAddPCs = null;
- downBranches = null;
- }
- }
+ /**
+ * overrides the visitor to initialize the opcode stack
+ *
+ * @param classContext
+ * the context object that holds the JavaClass being parsed
+ */
+ @Override
+ public void visitClassContext(ClassContext classContext) {
+ try {
+ stack = new OpcodeStack();
+ storeToAllocNumber = new HashMap<>();
+ allocLocation = new HashMap<>();
+ allocToAddPCs = new HashMap<>();
+ optionalRanges = new ArrayList<>();
+ super.visitClassContext(classContext);
+ } finally {
+ stack = null;
+ storeToAllocNumber = null;
+ allocLocation = null;
+ allocToAddPCs = null;
+ optionalRanges = null;
+ }
+ }
- /**
- * implements the visitor to reset the opcode stack
- *
- * @param obj
- * the context object of the currently parsed code block
- */
- @Override
- public void visitCode(Code obj) {
- stack.resetForMethodEntry(this);
- allocNumber = 0;
- allocLocation.clear();
- allocToAddPCs.clear();
- downBranches.clear();
- super.visitCode(obj);
+ /**
+ * implements the visitor to reset the opcode stack
+ *
+ * @param obj
+ * the context object of the currently parsed code block
+ */
+ @Override
+ public void visitCode(Code obj) {
+ stack.resetForMethodEntry(this);
+ nextAllocNumber = 1;
+ storeToAllocNumber.clear();
+ allocLocation.clear();
+ allocToAddPCs.clear();
+ optionalRanges.clear();
- for (List<Integer> pcs : allocToAddPCs.values()) {
- if (pcs.size() > 16) {
- bugReporter.reportBug(new BugInstance(this, BugType.PSC_PRESIZE_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
- .addSourceLine(this, pcs.get(0).intValue()));
- }
- }
- }
+ addExceptionRanges(obj);
- /**
- * implements the visitor to look for creation of collections that are then populated with a known number of elements usually based on another collection,
- * but the new collection is not presized.
- *
- * @param seen
- * the opcode of the currently parsed instruction
- */
- @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "CLI_CONSTANT_LIST_INDEX", justification = "Constrained by FindBugs API")
- @Override
- public void sawOpcode(int seen) {
- boolean sawAlloc = false;
- try {
- stack.precomputation(this);
+ super.visitCode(obj);
- switch (seen) {
- case INVOKESPECIAL:
- String clsName = getClassConstantOperand();
- if (PRESIZEABLE_COLLECTIONS.contains(clsName)) {
- String methodName = getNameConstantOperand();
- if (Values.CONSTRUCTOR.equals(methodName)) {
- String signature = getSigConstantOperand();
- if (SignatureBuilder.SIG_VOID_TO_VOID.equals(signature)) {
- sawAlloc = true;
- }
- }
- }
- break;
+ for (List<Integer> pcs : allocToAddPCs.values()) {
+ if (pcs.size() > 16) {
+ bugReporter.reportBug(new BugInstance(this, BugType.PSC_PRESIZE_COLLECTIONS.name(), NORMAL_PRIORITY)
+ .addClass(this).addMethod(this).addSourceLine(this, pcs.get(0).intValue()));
+ }
+ }
+ }
- case INVOKEINTERFACE:
- String methodName = getNameConstantOperand();
- if ("add".equals(methodName) || "addAll".equals(methodName)) {
- String signature = getSigConstantOperand();
- int numArguments = SignatureUtils.getNumParameters(signature);
- if ((numArguments == 1) && (stack.getStackDepth() > 1)) {
- OpcodeStack.Item item = stack.getStackItem(1);
- Integer allocNum = (Integer) item.getUserValue();
- if (allocNum != null) {
- if ("addAll".equals(methodName)) {
- allocToAddPCs.remove(allocNum);
- } else {
- List<Integer> lines = allocToAddPCs.get(allocNum);
- if (lines == null) {
- lines = new ArrayList<>();
- allocToAddPCs.put(allocNum, lines);
- }
- lines.add(Integer.valueOf(getPC()));
- }
- }
- }
- } else if ("put".equals(methodName) || "putAll".equals(methodName)) {
- String signature = getSigConstantOperand();
- int numArguments = SignatureUtils.getNumParameters(signature);
- if ((numArguments == 2) && (stack.getStackDepth() > 2)) {
- OpcodeStack.Item item = stack.getStackItem(2);
- Integer allocNum = (Integer) item.getUserValue();
- if (allocNum != null) {
- if ("putAll".equals(methodName)) {
- allocToAddPCs.remove(allocNum);
- } else {
- List<Integer> lines = allocToAddPCs.get(allocNum);
- if (lines == null) {
- lines = new ArrayList<>();
- allocToAddPCs.put(allocNum, lines);
- }
- lines.add(Integer.valueOf(getPC()));
- }
- }
- }
- }
- break;
+ /**
+ * implements the visitor to look for creation of collections that are then
+ * populated with a known number of elements usually based on another
+ * collection, but the new collection is not presized.
+ *
+ * @param seen
+ * the opcode of the currently parsed instruction
+ */
+ @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "CLI_CONSTANT_LIST_INDEX", justification = "Constrained by FindBugs API")
+ @Override
+ public void sawOpcode(int seen) {
+ Integer allocationNumber = null;
+ boolean sawAlloc = false;
+ try {
+ stack.precomputation(this);
- case LOOKUPSWITCH:
- case TABLESWITCH:
- int[] offsets = getSwitchOffsets();
- if (offsets.length > 1) {
- int secondCase = offsets[1] + getPC();
- DownBranch db = new DownBranch(getPC(), secondCase);
- downBranches.add(db);
- }
- break;
+ switch (seen) {
+ case INVOKESPECIAL:
+ String clsName = getClassConstantOperand();
+ if (PRESIZEABLE_COLLECTIONS.contains(clsName)) {
+ String methodName = getNameConstantOperand();
+ if (Values.CONSTRUCTOR.equals(methodName)) {
+ String signature = getSigConstantOperand();
+ if (SignatureBuilder.SIG_VOID_TO_VOID.equals(signature)) {
+ allocationNumber = Integer.valueOf(nextAllocNumber++);
+ sawAlloc = true;
+ }
+ }
+ }
+ break;
- case IFEQ:
- case IFNE:
- case IFLT:
- case IFLE:
- case IF_ICMPEQ:
- case IF_ICMPNE:
- case IF_ICMPLT:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- case IF_ACMPEQ:
- case IF_ACMPNE:
- case GOTO:
- case GOTO_W:
- if (getBranchOffset() < 0) {
- int target = getBranchTarget();
- Iterator<Map.Entry<Integer, List<Integer>>> it = allocToAddPCs.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<Integer, List<Integer>> entry = it.next();
- Integer allocLoc = allocLocation.get(entry.getKey());
- if ((allocLoc != null) && (allocLoc.intValue() < target)) {
- List<Integer> pcs = entry.getValue();
- for (int pc : pcs) {
- if (pc > target) {
- int numDownBranches = countDownBranches(target, pc);
- if (numDownBranches == 1) {
- bugReporter.reportBug(new BugInstance(this, BugType.PSC_PRESIZE_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this)
- .addMethod(this).addSourceLine(this, pc));
- it.remove();
- }
- break;
- }
- }
- }
- }
- } else {
- DownBranch db = new DownBranch(getPC(), getBranchTarget());
- downBranches.add(db);
- }
- break;
+ case INVOKEINTERFACE:
+ String methodName = getNameConstantOperand();
+ if ("add".equals(methodName) || "addAll".equals(methodName)) {
+ String signature = getSigConstantOperand();
+ int numArguments = SignatureUtils.getNumParameters(signature);
+ if ((numArguments == 1) && (stack.getStackDepth() > 1)) {
+ OpcodeStack.Item item = stack.getStackItem(1);
+ Integer allocNum = (Integer) item.getUserValue();
+ if (allocNum != null) {
+ if ("addAll".equals(methodName)) {
+ allocToAddPCs.remove(allocNum);
+ } else {
+ List<Integer> lines = allocToAddPCs.get(allocNum);
+ if (lines == null) {
+ lines = new ArrayList<>();
+ allocToAddPCs.put(allocNum, lines);
+ }
+ lines.add(Integer.valueOf(getPC()));
+ }
+ }
+ }
+ } else if ("put".equals(methodName) || "putAll".equals(methodName)) {
+ String signature = getSigConstantOperand();
+ int numArguments = SignatureUtils.getNumParameters(signature);
+ if ((numArguments == 2) && (stack.getStackDepth() > 2)) {
+ OpcodeStack.Item item = stack.getStackItem(2);
+ Integer allocNum = (Integer) item.getUserValue();
+ if (allocNum != null) {
+ if ("putAll".equals(methodName)) {
+ allocToAddPCs.remove(allocNum);
+ } else {
+ List<Integer> lines = allocToAddPCs.get(allocNum);
+ if (lines == null) {
+ lines = new ArrayList<>();
+ allocToAddPCs.put(allocNum, lines);
+ }
+ lines.add(Integer.valueOf(getPC()));
+ }
+ }
+ }
+ }
+ break;
- case IFNULL:
- case IFNONNULL:
- case IFGE:
- case IFGT:
- // null check and >, >= branches are hard to presize
- break;
- }
- } finally {
- stack.sawOpcode(this, seen);
- if (sawAlloc && (stack.getStackDepth() > 0)) {
- OpcodeStack.Item item = stack.getStackItem(0);
- ++allocNumber;
- item.setUserValue(Integer.valueOf(allocNumber));
- allocLocation.put(Integer.valueOf(allocNumber), Integer.valueOf(getPC()));
- }
- }
- }
+ case LOOKUPSWITCH:
+ case TABLESWITCH:
+ int[] offsets = getSwitchOffsets();
+ if (offsets.length >= 2) {
+ int pc = getPC();
+ int thisOffset = pc + offsets[0];
+ for (int o = 0; o < (offsets.length - 1); o++) {
+ int nextOffset = offsets[o + 1] + pc;
+ CodeRange db = new CodeRange(thisOffset, nextOffset);
+ optionalRanges.add(db);
+ thisOffset = nextOffset;
+ }
+ }
+ break;
- private int countDownBranches(int loopTop, int addPC) {
- int numDownBranches = 0;
- for (DownBranch db : downBranches) {
- if ((db.fromPC > loopTop) && (db.fromPC < addPC) && (db.toPC > addPC)) {
- numDownBranches++;
- }
- }
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFLE:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case GOTO:
+ case GOTO_W:
+ if (getBranchOffset() < 0) {
+ int target = getBranchTarget();
+ Iterator<Map.Entry<Integer, List<Integer>>> it = allocToAddPCs.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, List<Integer>> entry = it.next();
+ Integer allocLoc = allocLocation.get(entry.getKey());
+ if ((allocLoc != null) && (allocLoc.intValue() < target)) {
+ List<Integer> pcs = entry.getValue();
+ for (int pc : pcs) {
+ if (pc > target) {
+ int numDownBranches = countDownBranches(allocLoc.intValue(), pc);
+ if (numDownBranches == 1) {
+ bugReporter.reportBug(new BugInstance(this,
+ BugType.PSC_PRESIZE_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this)
+ .addMethod(this).addSourceLine(this, pc));
+ it.remove();
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ CodeRange db = new CodeRange(getPC(), getBranchTarget());
+ optionalRanges.add(db);
+ }
+ break;
- return numDownBranches;
- }
+ case IFNULL:
+ case IFNONNULL:
+ case IFGE:
+ case IFGT:
+ // null check and >, >= branches are hard to presize
+ if (getBranchOffset() > 0) {
+ CodeRange db = new CodeRange(getPC(), getBranchTarget());
+ optionalRanges.add(db);
+ }
+ break;
- static class DownBranch {
- public int fromPC;
- public int toPC;
+ case ASTORE:
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3: {
+ if (stack.getStackDepth() > 0) {
+ Integer alloc = (Integer) stack.getStackItem(0).getUserValue();
+ if (alloc != null) {
+ storeToAllocNumber.put(getRegisterOperand(), alloc);
+ }
+ }
+ }
+ break;
- DownBranch(int from, int to) {
- fromPC = from;
- toPC = to;
- }
+ case ALOAD:
+ case ALOAD_0:
+ case ALOAD_1:
+ case ALOAD_2:
+ case ALOAD_3: {
+ allocationNumber = storeToAllocNumber.get(getRegisterOperand());
+ }
+ break;
- @Override
- public String toString() {
- return ToString.build(this);
- }
- }
+ case PUTFIELD: {
+ if (stack.getStackDepth() > 0) {
+ Integer alloc = (Integer) stack.getStackItem(0).getUserValue();
+ if (alloc != null) {
+ storeToAllocNumber.put(getNameConstantOperand(), alloc);
+ }
+ }
+ }
+ break;
+
+ case GETFIELD: {
+ allocationNumber = storeToAllocNumber.get(getNameConstantOperand());
+ }
+
+ }
+ } finally {
+ stack.sawOpcode(this, seen);
+ if ((allocationNumber != null) && (stack.getStackDepth() > 0)) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ item.setUserValue(allocationNumber);
+ if (sawAlloc) {
+ allocLocation.put(allocationNumber, Integer.valueOf(getPC()));
+ }
+ }
+ }
+ }
+
+ private int countDownBranches(int allocationPos, int addPC) {
+ int numDownBranches = 0;
+ for (CodeRange db : optionalRanges) {
+ if ((db.fromPC > allocationPos) && (db.fromPC < addPC) && (db.toPC > addPC)) {
+ numDownBranches++;
+ }
+ }
+
+ return numDownBranches;
+ }
+
+ /**
+ * adds optionalRanges for all try/catch blocks
+ *
+ * @param c
+ * the currently parsed code object
+ */
+ private void addExceptionRanges(Code c) {
+
+ Map<CodeRange, List<Integer>> ranges = new HashMap<>();
+ CodeException[] ces = c.getExceptionTable();
+ if (ces != null) {
+ for (CodeException ce : ces) {
+ CodeRange range = new CodeRange(ce.getStartPC(), ce.getEndPC());
+ List<Integer> handlers = ranges.get(range);
+ if (handlers == null) {
+ handlers = new ArrayList<>(6);
+ ranges.put(range, handlers);
+ }
+ handlers.add(ce.getHandlerPC());
+ }
+ }
+
+ for (Map.Entry<CodeRange, List<Integer>> entry : ranges.entrySet()) {
+ optionalRanges.add(entry.getKey());
+ List<Integer> handlers = entry.getValue();
+ Collections.sort(handlers);
+ for (int h = 0; h < (handlers.size() - 1); h++) {
+ optionalRanges.add(new CodeRange(handlers.get(h), handlers.get(h + 1)));
+ }
+ }
+ }
+
+ static class CodeRange {
+ public int fromPC;
+ public int toPC;
+
+ CodeRange(int from, int to) {
+ fromPC = from;
+ toPC = to;
+ }
+
+ @Override
+ public int hashCode() {
+ return fromPC ^ toPC;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof CodeRange)) {
+ return false;
+ }
+
+ CodeRange that = (CodeRange) o;
+ return (fromPC == that.fromPC) && (toPC == that.toPC);
+ }
+
+ @Override
+ public String toString() {
+ return ToString.build(this);
+ }
+ }
}
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/SuspiciousUninitializedArray.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/SuspiciousUninitializedArray.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/detect/SuspiciousUninitializedArray.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -19,7 +19,11 @@
package com.mebigfatguy.fbcontrib.detect;
import java.util.BitSet;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
@@ -61,9 +65,12 @@
}
private final BugReporter bugReporter;
+ private boolean isEnum;
private OpcodeStack stack;
private String returnArraySig;
private BitSet uninitializedRegs;
+ private Map<Integer, Integer> arrayAliases;
+ private Map<Integer, SUAUserValue> storedUVs;
/**
* constructs a SUA detector given the reporter to report bugs on
@@ -84,12 +91,17 @@
@Override
public void visitClassContext(ClassContext classContext) {
try {
+ isEnum = classContext.getJavaClass().isEnum();
stack = new OpcodeStack();
uninitializedRegs = new BitSet();
+ arrayAliases = new HashMap<>();
+ storedUVs = new HashMap<>();
super.visitClassContext(classContext);
} finally {
stack = null;
uninitializedRegs = null;
+ arrayAliases = null;
+ storedUVs = null;
}
}
@@ -107,6 +119,10 @@
return;
}
+ if (isEnum && m.getName().equals("values")) {
+ return;
+ }
+
String sig = m.getSignature();
int sigPos = sig.indexOf(")[");
if (sigPos < 0) {
@@ -126,6 +142,8 @@
stack.resetForMethodEntry(this);
returnArraySig = sig.substring(sigPos + 1);
uninitializedRegs.clear();
+ arrayAliases.clear();
+ storedUVs.clear();
super.visitCode(obj);
}
@@ -132,7 +150,7 @@
/**
* overrides the visitor to annotate new array creation with a user value that denotes it as being uninitialized, and then if the array is populated to
* remove that user value. It then finds return values that have uninitialized arrays. byte arrays are not collected as creating a blank byte array is
- * probably a reasonably normal occurance.
+ * probably a reasonably normal occurrence.
*
* @param seen
* the context parameter of the currently parsed op code
@@ -147,7 +165,8 @@
case NEWARRAY: {
if (!isTOS0()) {
int typeCode = getIntConstant();
- if ((typeCode != Constants.T_BYTE) && returnArraySig.equals(SignatureUtils.toArraySignature(SignatureUtils.getTypeCodeSignature(typeCode)))) {
+ if ((typeCode != Constants.T_BYTE)
+ && returnArraySig.equals(SignatureUtils.toArraySignature(SignatureUtils.getTypeCodeSignature(typeCode)))) {
userValue = SUAUserValue.UNINIT_ARRAY;
}
}
@@ -195,7 +214,8 @@
}
item.setUserValue(null);
if (reg >= 0) {
- uninitializedRegs.clear(reg);
+ clearAliases(reg);
+ storedUVs.remove(reg);
}
}
}
@@ -234,7 +254,8 @@
}
item.setUserValue(null);
if (reg >= 0) {
- uninitializedRegs.clear(reg);
+ clearAliases(reg);
+ storedUVs.remove(reg);
}
} else {
// error condition - stack isn't right
@@ -252,9 +273,24 @@
if (stack.getStackDepth() > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
SUAUserValue uv = (SUAUserValue) item.getUserValue();
+ storedUVs.put(Integer.valueOf(reg), uv);
uninitializedRegs.set(reg, (uv != null) && (uv.isUnitializedArray()));
+ Integer aliasReg = arrayAliases.get(reg);
+ if (aliasReg != null) {
+ uninitializedRegs.set(aliasReg, (uv != null) && (uv.isUnitializedArray()));
+ }
+
+ int targetReg = item.getRegisterNumber();
+ if ((targetReg >= 0) && (targetReg != reg)) {
+ arrayAliases.put(reg, targetReg);
+ } else if ((uv != null) && uv.isRegister()) {
+ arrayAliases.put(reg, uv.getRegister());
+ } else {
+ arrayAliases.remove(reg);
+ }
} else {
- uninitializedRegs.clear(reg);
+ clearAliases(reg);
+ storedUVs.remove(Integer.valueOf(reg));
}
}
break;
@@ -265,9 +301,7 @@
case ALOAD_2:
case ALOAD_3: {
int reg = RegisterUtils.getALoadReg(this, seen);
- if (uninitializedRegs.get(reg)) {
- userValue = SUAUserValue.UNINIT_ARRAY;
- }
+ userValue = storedUVs.get(Integer.valueOf(reg));
}
break;
@@ -277,7 +311,8 @@
item.setUserValue(null);
int reg = item.getRegisterNumber();
if (reg >= 0) {
- uninitializedRegs.clear(reg);
+ clearAliases(reg);
+ storedUVs.remove(reg);
}
}
}
@@ -288,7 +323,6 @@
OpcodeStack.Item item = stack.getStackItem(0);
SUAUserValue uv = (SUAUserValue) item.getUserValue();
if ((uv != null) && (uv.isUnitializedArray())) {
-
bugReporter.reportBug(new BugInstance(this, BugType.SUA_SUSPICIOUS_UNINITIALIZED_ARRAY.name(), NORMAL_PRIORITY).addClass(this)
.addMethod(this).addSourceLine(this));
}
@@ -296,16 +330,21 @@
}
break;
+ case DUP:
+ if (stack.getStackDepth() > 0) {
+ OpcodeStack.Item item = stack.getStackItem(0);
+ userValue = (SUAUserValue) item.getUserValue();
+ }
+ break;
+
default:
break;
}
- } finally
-
- {
+ } finally {
TernaryPatcher.pre(stack, seen);
stack.sawOpcode(this, seen);
TernaryPatcher.post(stack, seen);
- if (stack.getStackDepth() > 0) {
+ if ((Constants.PRODUCE_STACK[seen] > 0) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item item = stack.getStackItem(0);
item.setUserValue(userValue);
}
@@ -312,6 +351,41 @@
}
}
+ private void clearAliases(int reg) {
+
+ clearClosureAliases(reg, new BitSet());
+ }
+
+ private void clearClosureAliases(int reg, BitSet alreadyCleared) {
+
+ if (alreadyCleared.get(reg)) {
+ return;
+ }
+
+ uninitializedRegs.clear(reg);
+ alreadyCleared.set(reg);
+ if (uninitializedRegs.isEmpty()) {
+ return;
+ }
+
+ Integer targetReg = arrayAliases.get(reg);
+ if (targetReg != null) {
+ clearClosureAliases(targetReg, alreadyCleared);
+ }
+
+ Set<Integer> clear = new HashSet<>();
+ for (Map.Entry<Integer, Integer> entry : arrayAliases.entrySet()) {
+ targetReg = entry.getValue();
+ if (targetReg.equals(reg)) {
+ clear.add(entry.getKey());
+ }
+ }
+
+ for (Integer cr : clear) {
+ clearClosureAliases(cr, alreadyCleared);
+ }
+ }
+
private boolean isTOS0() {
if (stack.getStackDepth() == 0) {
return false;
Modified: trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/utils/ToString.java
===================================================================
--- trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/utils/ToString.java 2017-07-19 21:31:58 UTC (rev 1824)
+++ trunk/fb-contrib/src/main/java/com/mebigfatguy/fbcontrib/utils/ToString.java 2017-09-04 17:52:07 UTC (rev 1825)
@@ -24,80 +24,85 @@
import java.util.HashSet;
import java.util.Set;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
/**
* an automatic toString() builder using reflection
*/
public class ToString {
- /**
- * holds objects that have already been converted to string to avoid infinite loops in the toString generation
- */
- private static class VisitedInfo {
- Set<Integer> visited = new HashSet<>();
- int count = 0;
- }
+ /**
+ * holds objects that have already been converted to string to avoid infinite
+ * loops in the toString generation
+ */
+ private static class VisitedInfo {
+ Set<Integer> visited = new HashSet<>();
+ int count = 0;
+ }
- private static final ThreadLocal<VisitedInfo> visited = new ThreadLocal<VisitedInfo>() {
+ private static final ThreadLocal<VisitedInfo> visited = new ThreadLocal<VisitedInfo>() {
- @Override
- protected VisitedInfo initialValue() {
- return new VisitedInfo();
- }
- };
+ @Override
+ protected VisitedInfo initialValue() {
+ return new VisitedInfo();
+ }
+ };
- private ToString() {
- }
+ private ToString() {
+ }
- public static String build(Object o, String... ignoredFields) {
- VisitedInfo vi = visited.get();
- try {
- vi.count++;
- return generate(o, (ignoredFields == null) ? null : Arrays.<String> asList(ignoredFields), vi.visited);
- } finally {
- if (--vi.count == 0) {
- vi.visited.clear();
- }
- }
- }
+ public static String build(Object o, String... ignoredFields) {
+ VisitedInfo vi = visited.get();
+ try {
+ vi.count++;
+ return generate(o, (ignoredFields == null) ? null : Arrays.<String>asList(ignoredFields), vi.visited);
+ } finally {
+ if (--vi.count == 0) {
+ vi.visited.clear();
+ }
+ }
+ }
- private static String generate(Object o, Collection<String> ignoredFields, Set<Integer> visitedObjects) {
+ @SuppressFBWarnings(value = "RFI_SET_ACCESSIBLE", justification = "No other simple way to to show value of object")
+ private static String generate(Object o, Collection<String> ignoredFields, Set<Integer> visitedObjects) {
- StringBuilder sb = new StringBuilder(100);
- Class<?> cls = o.getClass();
- Integer identityHC = Integer.valueOf(System.identityHashCode(o));
- sb.append(cls.getSimpleName()).append('[').append(identityHC).append("]{");
+ StringBuilder sb = new StringBuilder(100);
+ Class<?> cls = o.getClass();
+ Integer identityHC = Integer.valueOf(System.identityHashCode(o));
+ sb.append(cls.getSimpleName()).append('[').append(identityHC).append("]{");
- if (!visitedObjects.contains(identityHC)) {
- try {
- visitedObjects.add(identityHC);
- String sep = "";
- for (Field f : cls.getDeclaredFields()) {
- String fieldName = f.getName();
- if (!f.isSynthetic() && !fieldName.contains("$") && ((ignoredFields == null) || !ignoredFields.contains(fieldName))) {
- sb.append(sep);
- sep = ", ";
- sb.append(fieldName).append('=');
- try {
- f.setAccessible(true);
- Object value = f.get(o);
- if (value == null) {
- sb.append((String) null);
- } else if (value.getClass().isArray()) {
- sb.append(Arrays.toString((Object[]) value));
- } else {
- sb.append(value);
- }
- } catch (SecurityException e) {
- sb.append("*SECURITY_EXCEPTION*");
- }
- }
- }
- } catch (IllegalAccessException | RuntimeException e) {
- // if we get an exception show as much as we can get
- }
- }
+ if (!visitedObjects.contains(identityHC)) {
+ try {
+ visitedObjects.add(identityHC);
+ String sep = "";
+ for (Field f : cls.getDeclaredFields()) {
+ String fieldName = f.getName();
+ if (!f.isSynthetic() && !fieldName.contains("$")
+ && ((ignoredFields == null) || !ignoredFields.contains(fieldName))) {
+ sb.append(sep);
+ sep = ", ";
+ sb.append(fieldName).append('=');
+ try {
+ f.setAccessible(true);
+ Object value = f.get(o);
+ if (value == null) {
+ sb.append((String) null);
+ } else if (value.getClass().isArray()) {
+ sb.append(Arrays.toString((Object[]) value));
+ } else {
+ sb.append(value);
+ }
+ } catch (SecurityException e) {
+ sb.append("*SECURITY_EXCEPTION*");
+ }
+ }
+ }
+ } catch (IllegalAccessException | RuntimeException e) {
+ // if we get an exception show as much as we can get
+ }
+ }
- sb.a...
[truncated message content] |