[Fb-contrib-commit] SF.net SVN: fb-contrib:[1367] trunk/fb-contrib/src/com/mebigfatguy/ fbcontrib/
Brought to you by:
dbrosius
|
From: <dbr...@us...> - 2009-10-15 03:33:59
|
Revision: 1367
http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=1367&view=rev
Author: dbrosius
Date: 2009-10-15 03:33:46 +0000 (Thu, 15 Oct 2009)
Log Message:
-----------
add new detector CVAA - by Bhaskar Maddala
Added Paths:
-----------
trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ContraVariantArrayAssignment.java
Added: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ContraVariantArrayAssignment.java
===================================================================
--- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ContraVariantArrayAssignment.java (rev 0)
+++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ContraVariantArrayAssignment.java 2009-10-15 03:33:46 UTC (rev 1367)
@@ -0,0 +1,169 @@
+/*
+ * fb-contrib - Auxiliary detectors for Java programs
+ * Copyright (C) 2009 Bhaskar Maddala
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package com.mebigfatguy.fbcontrib.detect;
+
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.LocalVariable;
+import org.apache.bcel.classfile.LocalVariableTable;
+import org.apache.bcel.generic.ArrayType;
+import org.apache.bcel.generic.ObjectType;
+import org.apache.bcel.generic.Type;
+
+import com.mebigfatguy.fbcontrib.utils.RegisterUtils;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.BytecodeScanningDetector;
+import edu.umd.cs.findbugs.OpcodeStack;
+
+/**
+ * Finds contravariant array assignments. Since arrays are mutable data structures, their use
+ * must be restricted to covariant or invariant usage
+ *
+ * <pre>
+ * class A {}
+ * class B extends A {}
+ *
+ * B[] b = new B[2];
+ * A[] a = b;
+ * a[0] = new A(); // results in ArrayStoreException (Runtime)
+ * </pre>
+ *
+ */
+public class ContraVariantArrayAssignment extends BytecodeScanningDetector {
+ private final BugReporter bugReporter;
+ private final OpcodeStack stack;
+
+ /**
+ * constructs a CVAA detector given the reporter to report bugs on.
+
+ * @param bugReporter the sync of bug reports
+ */
+ public ContraVariantArrayAssignment(final BugReporter bugReporter) {
+ this.bugReporter = bugReporter;
+ this.stack = new OpcodeStack();
+ }
+
+ /**
+ * implements the visitor to pass through constructors and static initializers to the
+ * byte code scanning code. These methods are not reported, but are used to build
+ * SourceLineAnnotations for fields, if accessed.
+ *
+ * @param obj the context object of the currently parsed code attribute
+ */
+ @Override
+ public void visitCode(Code obj) {
+ stack.resetForMethodEntry(this);
+ LocalVariableTable lvt = getMethod().getLocalVariableTable();
+ if(lvt != null) {
+ super.visitCode(obj);
+ }
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ try{
+ switch(seen){
+ case ASTORE:
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3:
+ if(stack.getStackDepth() > 0){
+ OpcodeStack.Item item = stack.getStackItem(0);
+ String sourceSignature = item.getSignature();
+ LocalVariable lv = getMethod().getLocalVariableTable()
+ .getLocalVariable(RegisterUtils.getAStoreReg(this, seen), getNextPC());
+ if(lv != null){
+ String targetSignature = lv.getSignature();
+ checkSignatures(sourceSignature, targetSignature);
+ }
+ }
+ break;
+ case PUTFIELD:
+ case PUTSTATIC:
+ if(stack.getStackDepth() > 0){
+ OpcodeStack.Item item = stack.getStackItem(0);
+ String sourceSignature = item.getSignature();
+ String targetSignature = getSigConstantOperand();
+ checkSignatures(sourceSignature, targetSignature);
+ }
+ break;
+ case INVOKESTATIC:
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE:
+ case INVOKESPECIAL:
+ if(stack.getStackDepth() > 0){
+ String signature = getSigConstantOperand();
+ checkMethodInvocation(signature);
+ }
+ break;
+ }
+ super.sawOpcode(seen);
+ }
+ finally{
+ stack.sawOpcode(this, seen);
+ }
+ }
+
+ private boolean isArrayType(String signature){
+ return Type.getType(signature) instanceof ArrayType;
+ }
+
+ private boolean isObjectType(String signature){
+ return ((ArrayType)Type.getType(signature)).getBasicType() instanceof ObjectType;
+ }
+
+ private void checkSignatures(String sourceSignature, String targetSignature) {
+ try{
+ if(isArrayType(sourceSignature)) {
+ if(!isArrayType(targetSignature)){
+ bugReporter.reportBug(new BugInstance(this, "CVAA_CONTRAVARIANT_ARRAY_ASSIGNMENT", HIGH_PRIORITY)
+ .addClass(this)
+ .addMethod(this)
+ .addSourceLine(this));
+ } else {
+ if(isObjectType(sourceSignature) && isObjectType(targetSignature)){
+ ObjectType sourceType = (ObjectType) ((ArrayType) Type.getType(sourceSignature)).getBasicType();
+ ObjectType targetType = (ObjectType) ((ArrayType) Type.getType(targetSignature)).getBasicType();
+ if(sourceType.subclassOf(targetType) && !targetType.subclassOf(sourceType)) {
+ bugReporter.reportBug(new BugInstance(this, "CVAA_CONTRAVARIANT_ARRAY_ASSIGNMENT", HIGH_PRIORITY)
+ .addClass(this)
+ .addMethod(this)
+ .addSourceLine(this));
+ }
+ }
+ }
+ }
+ }
+ catch(ClassNotFoundException cnfe) {
+ bugReporter.reportMissingClass(cnfe);
+ }
+ }
+
+ private void checkMethodInvocation(String signature) {
+ Type[] types = Type.getArgumentTypes(signature);
+ for(int i = 0; i < types.length; i++){
+ String targetSignature = types[i].getSignature();
+ OpcodeStack.Item item = stack.getStackItem(types.length - i - 1);
+ String sourceSignature = item.getSignature();
+ checkSignatures(sourceSignature, targetSignature);
+ }
+ }
+}
Property changes on: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ContraVariantArrayAssignment.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|