[Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect CopiedOverriddenMethod.java,1.2,
Brought to you by:
dbrosius
|
From: Dave B. <dbr...@us...> - 2005-12-09 04:24:17
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29417/src/com/mebigfatguy/fbcontrib/detect Modified Files: CopiedOverriddenMethod.java Log Message: can't get away with just comparing bytes... Now compare instruction by instruction. For most instructions, comparing instructions for sameness is ok, but for now, FieldInstructions be careful that it really is the same field in the same class. Others may show up, as well. Index: CopiedOverriddenMethod.java =================================================================== RCS file: /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- CopiedOverriddenMethod.java 9 Dec 2005 02:33:37 -0000 1.2 +++ CopiedOverriddenMethod.java 9 Dec 2005 04:24:09 -0000 1.3 @@ -18,18 +18,23 @@ */ package com.mebigfatguy.fbcontrib.detect; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.BranchInstruction; +import org.apache.bcel.generic.ConstantPoolGen; +import org.apache.bcel.generic.FieldInstruction; +import org.apache.bcel.generic.Instruction; +import org.apache.bcel.generic.InstructionHandle; +import org.apache.bcel.generic.InstructionList; +import org.apache.bcel.generic.ReferenceType; import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.Detector; -import edu.umd.cs.findbugs.SourceLineAnnotation; import edu.umd.cs.findbugs.StatelessDetector; import edu.umd.cs.findbugs.ba.ClassContext; import edu.umd.cs.findbugs.visitclass.DismantleBytecode; @@ -40,6 +45,7 @@ private Map<String, Code> superclassCode = new HashMap<String, Code>(); private ClassContext classContext; private String curMethodInfo; + private ConstantPoolGen childPoolGen, parentPoolGen; /** * constructs a COM detector given the reporter to report bugs on @@ -73,6 +79,8 @@ this.classContext = classContext; superclassCode.clear(); JavaClass superCls = cls.getSuperClass(); + childPoolGen = new ConstantPoolGen(cls.getConstantPool()); + parentPoolGen = new ConstantPoolGen(superCls.getConstantPool()); Method[] methods = superCls.getMethods(); for (Method m : methods) { String methodName = m.getName(); @@ -85,6 +93,8 @@ } cls.accept(this); superclassCode.clear(); + childPoolGen = null; + parentPoolGen = null; } } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); @@ -112,7 +122,7 @@ Code superCode = superclassCode.get(curMethodInfo); if (superCode != null) { - if (Arrays.equals(obj.getCode(), superCode.getCode())) { + if (codeEquals(obj, superCode)) { bugReporter.reportBug(new BugInstance(this, "COM_COPIED_OVERRIDDEN_METHOD", NORMAL_PRIORITY) .addClass(this) .addMethod(this) @@ -122,6 +132,65 @@ } /** + * compares two code blocks to see if they are equal with regard to instructions and field accesses + * + * @param code1 the first code block + * @param code2 the second code block + * + * @return whether the code blocks are the same + */ + public boolean codeEquals(Code child, Code parent) { + byte[] childBytes = child.getCode(); + byte[] parentBytes = parent.getCode(); + + if ((childBytes == null) || (parentBytes == null)) + return false; + + if (childBytes.length != parentBytes.length) + return false; + + InstructionHandle[] childihs = new InstructionList(childBytes).getInstructionHandles(); + InstructionHandle[] parentihs = new InstructionList(parentBytes).getInstructionHandles(); + + if (childihs.length != parentihs.length) + return false; + + for (int i = 0; i < childihs.length; i++) { + InstructionHandle childih = childihs[i]; + InstructionHandle parentih = parentihs[i]; + Instruction childin = childih.getInstruction(); + Instruction parentin = parentih.getInstruction(); + + if (!childin.getName().equals(parentin.getName())) + return false; + + if (childin instanceof FieldInstruction) { + String childFName = ((FieldInstruction) childin).getFieldName(childPoolGen); + String parentFName = ((FieldInstruction) parentin).getFieldName(parentPoolGen); + if (!childFName.equals(parentFName)) + return false; + String childFSig = ((FieldInstruction) childin).getSignature(childPoolGen); + String parentFSig = ((FieldInstruction) parentin).getSignature(parentPoolGen); + if (!childFSig.equals(parentFSig)) + return false; + + if (childFSig.charAt(0) == 'L') { + ReferenceType childRefType = ((FieldInstruction) childin).getReferenceType(childPoolGen); + ReferenceType parentRefType = ((FieldInstruction) parentin).getReferenceType(parentPoolGen); + if (!childRefType.getSignature().equals(parentRefType.getSignature())) + return false; + } + } else { + if (!childin.equals(parentin)) + return false; + } + + } + + return true; + } + + /** * implements the detector with an empty implementation */ public void report() { |