[Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect JDBCVendorReliance.java,1.1,1.2
Brought to you by:
dbrosius
From: Dave B. <dbr...@us...> - 2006-03-07 03:33:14
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15253/src/com/mebigfatguy/fbcontrib/detect Modified Files: JDBCVendorReliance.java Log Message: centralize checking of jdbc class, and respect local variable ranges Index: JDBCVendorReliance.java =================================================================== RCS file: /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/JDBCVendorReliance.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- JDBCVendorReliance.java 6 Mar 2006 04:16:37 -0000 1.1 +++ JDBCVendorReliance.java 7 Mar 2006 03:33:11 -0000 1.2 @@ -1,8 +1,11 @@ package com.mebigfatguy.fbcontrib.detect; -import java.util.HashSet; -import java.util.Set; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.apache.bcel.classfile.LocalVariable; +import org.apache.bcel.classfile.LocalVariableTable; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.Type; @@ -20,7 +23,7 @@ private BugReporter bugReporter; private OpcodeStack stack = new OpcodeStack(); - private Set<Integer> jdbcLocals = new HashSet<Integer>(); + private Map<Integer, Integer> jdbcLocals = new HashMap<Integer, Integer>(); /** * constructs a JVR detector given the reporter to report bugs on @@ -54,10 +57,8 @@ int reg = obj.isStatic() ? 0 : 1; for (Type arg : argTypes) { String sig = arg.getSignature(); - if (sig.startsWith("Ljavax/sql/") - || sig.startsWith("Ljava/sql/")) { - jdbcLocals.add(new Integer(reg)); - } + if (isJDBCClass(sig)) + jdbcLocals.put(new Integer(reg), new Integer(getLocalVariableEndRange(reg, 1))); reg += (sig.equals("L") || sig.equals("D")) ? 2 : 1; } @@ -68,11 +69,19 @@ try { stack.mergeJumps(this); + int curPC = getPC(); + Iterator<Integer> it = jdbcLocals.values().iterator(); + while (it.hasNext()) { + Integer endPCRange = it.next(); + if (endPCRange.intValue() < curPC) { + it.remove(); + } + } + if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) { String clsName = getClassConstantOperand(); - if (!clsName.startsWith("javax/sql/") - && !clsName.startsWith("java/sql")) { + if (!isJDBCClass(clsName)) { int parmCnt = Type.getArgumentTypes(getSigConstantOperand()).length; if (stack.getStackDepth() > parmCnt) { OpcodeStack.Item itm = stack.getStackItem(parmCnt); @@ -89,28 +98,25 @@ if (seen == INVOKEINTERFACE) { String infName = getClassConstantOperand(); - if (infName.startsWith("javax/sql/") - || infName.startsWith("java/sql/")) { + if (isJDBCClass(infName)) { String sig = getSigConstantOperand(); Type retType = Type.getReturnType(sig); infName = retType.getSignature(); - if (infName.startsWith("Ljavax/sql/") - || infName.startsWith("Ljava/sql/")) { + if (isJDBCClass(infName)) tosIsJDBC = true; - } } } else if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); if (itm.getUserValue() != null) { int reg = getAStoreReg(seen); - jdbcLocals.add(new Integer(reg)); + jdbcLocals.put(new Integer(reg), new Integer(getLocalVariableEndRange(reg, getPC()))); } } } else if ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) { int reg = getALoadReg(seen); - if (jdbcLocals.contains(new Integer(reg))) + if (jdbcLocals.containsKey(new Integer(reg))) tosIsJDBC = true; } } finally { @@ -147,4 +153,43 @@ return getRegisterOperand(); return seen - ALOAD_0; } + + /** + * returns the end pc of the visible range of this register at this pc + * + * @param reg the register to examine + * @param curPC the pc of the current instruction + * @return the endpc + */ + private int getLocalVariableEndRange(int reg, int curPC) { + int endRange = Integer.MAX_VALUE; + LocalVariableTable lvt = this.getMethod().getLocalVariableTable(); + if (lvt != null) { + LocalVariable lv = lvt.getLocalVariable(reg, curPC); + if (lv != null) + endRange = lv.getStartPC() + lv.getLength(); + } + return endRange; + } + + /** + * returns whether the class is a jdbc class + * + * @param a class name or signature of a class + * + * @return if the class name is a jdbc one + */ + private boolean isJDBCClass(String clsName) { + if (clsName.endsWith(";")) + clsName = clsName.substring(1, clsName.length() - 1); + clsName = clsName.replace('.', '/'); + + if (!clsName.startsWith("java/sql/") + && !clsName.startsWith("javax/sql/")) + return false; + + if (clsName.endsWith("Exception")) + return false; + return true; + } } |