[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] |