Thread: [Fb-contrib-commit] SF.net SVN: fb-contrib: [665] trunk/fb-contrib/src/com/mebigfatguy/ fbcontrib/
Brought to you by:
dbrosius
From: <dbr...@us...> - 2006-10-10 05:58:57
|
Revision: 665 http://svn.sourceforge.net/fb-contrib/?rev=665&view=rev Author: dbrosius Date: 2006-10-09 22:58:53 -0700 (Mon, 09 Oct 2006) Log Message: ----------- fix false positive due to putting enums into sets/maps, when you only know that the set or map is the interface, not any particular concrete class. Modified Paths: -------------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java 2006-10-10 04:06:06 UTC (rev 664) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java 2006-10-10 05:58:53 UTC (rev 665) @@ -18,13 +18,18 @@ */ package com.mebigfatguy.fbcontrib.detect; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import org.apache.bcel.Constants; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; +import com.mebigfatguy.fbcontrib.utils.Integer14; +import com.mebigfatguy.fbcontrib.utils.RegisterUtils; + import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.BytecodeScanningDetector; @@ -38,9 +43,20 @@ */ public class UseEnumCollections extends BytecodeScanningDetector { + private static final Set<String> nonEnumCollections = new HashSet<String>(); + static { + nonEnumCollections.add("Ljava/util/HashSet;"); + nonEnumCollections.add("Ljava/util/HashMap;"); + nonEnumCollections.add("Ljava/util/TreeMap;"); + nonEnumCollections.add("Ljava/util/ConcurrentHashMap"); + nonEnumCollections.add("Ljava/util/IdentityHashMap;"); + nonEnumCollections.add("Ljava/util/WeakHashMap;"); + } private BugReporter bugReporter; private OpcodeStack stack; private Set<String> checkedFields; + private Map<Integer, Boolean> enumRegs; + private Map<String, Boolean> enumFields; private boolean methodReported; /** * constructs a UEC detector given the reporter to report bugs on @@ -61,11 +77,15 @@ if (cls.getMajor() >= Constants.MAJOR_1_5) { stack = new OpcodeStack(); checkedFields = new HashSet<String>(); + enumRegs = new HashMap<Integer, Boolean>(); + enumFields = new HashMap<String, Boolean>(); super.visitClassContext(classContext); } } finally { stack = null; checkedFields = null; + enumRegs = null; + enumFields = null; } } @@ -77,17 +97,55 @@ public void visitMethod(Method obj) { stack.resetForMethodEntry(this); methodReported = false; + enumRegs.clear(); super.visitMethod(obj); } public void sawOpcode(int seen) { + Boolean sawEnumCollectionCreation = null; //true - enum, false - nonenum try { stack.mergeJumps(this); if (methodReported) return; - if (seen == INVOKEINTERFACE) { + if (seen == INVOKESTATIC) { + String clsName = getClassConstantOperand(); + String signature = getSigConstantOperand(); + if ("java/util/EnumSet".equals(clsName) && signature.endsWith(")Ljava/util/EnumSet;")) + sawEnumCollectionCreation = Boolean.TRUE; + } else if (seen == INVOKESPECIAL) { + String clsName = getClassConstantOperand(); + String methodName = getNameConstantOperand(); + if ("java/util/EnumMap".equals(clsName) && "<init>".equals(methodName)) + sawEnumCollectionCreation = Boolean.TRUE; + else if (clsName.startsWith("java/util/")) { + if (clsName.endsWith("Map") || clsName.endsWith("Set")) + sawEnumCollectionCreation = Boolean.FALSE; + } + } else if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + Integer reg = Integer14.valueOf(RegisterUtils.getAStoreReg(this, seen)); + if (itm.getUserValue() != null) + enumRegs.put(reg, (Boolean)itm.getUserValue()); + else + enumRegs.remove(reg); + } + } else if ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) { + Integer reg = Integer14.valueOf(RegisterUtils.getALoadReg(this, seen)); + sawEnumCollectionCreation = enumRegs.get(reg); + } else if (seen == PUTFIELD) { + String fieldName = getNameConstantOperand(); + OpcodeStack.Item itm = stack.getStackItem(0); + if (itm.getUserValue() != null) + enumFields.put(fieldName, (Boolean)itm.getUserValue()); + else + enumFields.remove(fieldName); + } else if (seen == GETFIELD) { + String fieldName = getNameConstantOperand(); + sawEnumCollectionCreation = enumFields.get(fieldName); + } else if (seen == INVOKEINTERFACE) { boolean bug = false; String clsName = getClassConstantOperand(); String methodName = getNameConstantOperand(); @@ -95,11 +153,11 @@ if (("java/util/Map".equals(clsName)) && ("put".equals(methodName)) && ("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;".equals(signature))) { - bug = isEnum(1) && !isEnumCollection(1) && alreadyReported(2); + bug = isEnum(1) && !isEnumCollection(2) && !alreadyReported(2); } else if (("java/util/Set".equals(clsName)) && ("add".equals(methodName)) && ("(Ljava/lang/Object;)Z".equals(signature))) { - bug = isEnum(0) && !isEnumCollection(1) && alreadyReported(1); + bug = isEnum(0) && !isEnumCollection(1) && !alreadyReported(1); } if (bug) { @@ -114,6 +172,12 @@ bugReporter.reportMissingClass(cnfe); } finally { stack.sawOpcode(this, seen); + if (sawEnumCollectionCreation != null) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item itm = stack.getStackItem(0); + itm.setUserValue(sawEnumCollectionCreation); + } + } } } @@ -137,7 +201,7 @@ /** * returns whether the item at the stackpos location is an instance of an EnumSet or EnumMap * - * @param stackPos the posotion on the opstack to check + * @param stackPos the position on the opstack to check * * @return whether the class is an EnumSet or EnumMap */ @@ -146,8 +210,20 @@ return false; OpcodeStack.Item item = stack.getStackItem(stackPos); + + Boolean userValue = (Boolean)item.getUserValue(); + if (userValue != null) + return userValue.booleanValue(); + String realClass = item.getSignature(); - return "Ljava/util/EnumSet;".equals(realClass) || "Ljava/util/EnumMap;".equals(realClass); + if ("Ljava/util/EnumSet;".equals(realClass) || "Ljava/util/EnumMap;".equals(realClass)) + return true; + + if (nonEnumCollections.contains(realClass)) + return false; + + //Can't tell here so return true + return true; } /** @@ -162,12 +238,12 @@ OpcodeStack.Item item = stack.getStackItem(stackPos); FieldAnnotation fa = item.getField(); if (fa == null) - return true; + return false; else { String fieldName = fa.getFieldName(); boolean checked = checkedFields.contains(fieldName); checkedFields.add(fieldName); - return !checked; + return checked; } } return false; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dbr...@us...> - 2008-01-18 17:12:30
|
Revision: 987 http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=987&view=rev Author: dbrosius Date: 2008-01-18 09:09:52 -0800 (Fri, 18 Jan 2008) Log Message: ----------- guard against OpcodeStack having problems Modified Paths: -------------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java 2008-01-17 22:48:05 UTC (rev 986) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java 2008-01-18 17:09:52 UTC (rev 987) @@ -139,12 +139,14 @@ Integer reg = Integer14.valueOf(RegisterUtils.getALoadReg(this, seen)); sawEnumCollectionCreation = enumRegs.get(reg); } else if (seen == PUTFIELD) { - String fieldName = getNameConstantOperand(); - OpcodeStack.Item itm = stack.getStackItem(0); - if (itm.getUserValue() != null) - enumFields.put(fieldName, (Boolean)itm.getUserValue()); - else - enumFields.remove(fieldName); + if (stack.getStackDepth() > 0) { + String fieldName = getNameConstantOperand(); + OpcodeStack.Item itm = stack.getStackItem(0); + if (itm.getUserValue() != null) + enumFields.put(fieldName, (Boolean)itm.getUserValue()); + else + enumFields.remove(fieldName); + } } else if (seen == GETFIELD) { String fieldName = getNameConstantOperand(); sawEnumCollectionCreation = enumFields.get(fieldName); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |