1 20 package edu.umd.cs.findbugs.detect; 21 22 23 import edu.umd.cs.findbugs.*; 24 import edu.umd.cs.findbugs.ba.ClassContext; 25 import java.util.*; 26 import org.apache.bcel.Repository; 27 import org.apache.bcel.classfile.*; 28 29 30 public class MultithreadedInstanceAccess extends BytecodeScanningDetector 31 { 32 private static final String STRUTS_ACTION_NAME = "org.apache.struts.action.Action"; 33 private static final String SERVLET_NAME = "javax.servlet.Servlet"; 34 private BugReporter bugReporter; 35 private Set<JavaClass> mtClasses; 36 private String mtClassName; 37 private int monitorCount; 38 private boolean writingField; 39 private Set<String > alreadyReported; 40 41 public MultithreadedInstanceAccess(BugReporter bugReporter) { 42 this.bugReporter = bugReporter; 43 } 44 45 private Set<JavaClass> getMtClasses() { 46 if (mtClasses != null) 47 return mtClasses; 48 49 mtClasses = new HashSet<JavaClass>(); 50 try { 51 mtClasses.add(Repository.lookupClass(STRUTS_ACTION_NAME)); 52 } catch (ClassNotFoundException cnfe) { 53 } 55 try { 56 mtClasses.add(Repository.lookupClass(SERVLET_NAME)); 57 } catch (ClassNotFoundException cnfe) { 58 } 60 61 return mtClasses; 62 } 63 64 @Override 65 public void visitClassContext(ClassContext classContext) { 66 try { 67 JavaClass cls = classContext.getJavaClass(); 68 String superClsName = cls.getSuperclassName(); 69 if ("java.lang.Object".equals(superClsName)) 70 return; 71 72 if (STRUTS_ACTION_NAME.equals(superClsName)) { 73 mtClassName = STRUTS_ACTION_NAME; 74 super.visitClassContext(classContext); 75 } 76 else if (SERVLET_NAME.equals(superClsName)) { 77 mtClassName = SERVLET_NAME; 78 super.visitClassContext(classContext); 79 } 80 else { 81 for (JavaClass mtClass : getMtClasses()) { 82 88 if (mtClass.isClass() ? cls.instanceOf(mtClass) : cls.implementationOf(mtClass)) { 89 mtClassName = mtClass.getClassName(); 90 super.visitClassContext(classContext); 91 return; 92 } 93 } 94 } 95 } catch (Exception e) { 96 } 98 } 99 100 @Override 101 public void visitMethod(Method obj) { 102 monitorCount = 0; 103 alreadyReported = new HashSet<String >(); 104 writingField = false; 105 } 106 107 @Override 108 public void visitCode(Code obj) { 109 if (!getMethodName().equals("<init>") && !getMethodName().equals("init")) 110 super.visitCode(obj); 111 } 112 113 @Override 114 public void sawField() { 115 if ((monitorCount > 0) || (!writingField)) 116 return; 117 118 ConstantFieldref fieldRef; 119 Constant c = getConstantRefOperand(); 120 if (c instanceof ConstantFieldref) { 121 fieldRef = (ConstantFieldref)c; 122 123 String className = fieldRef.getClass(getConstantPool()).replace('.', '/'); 124 if (className.equals( this.getClassName())) { 125 ConstantPool cp = getConstantPool(); 126 int nameAndTypeIdx = fieldRef.getNameAndTypeIndex(); 127 ConstantNameAndType ntc = (ConstantNameAndType)cp.getConstant(nameAndTypeIdx); 128 int nameIdx = ntc.getNameIndex(); 129 130 Field[] flds = getClassContext().getJavaClass().getFields(); 131 132 for (Field fld : flds) { 133 if (fld.getNameIndex() == nameIdx) { 134 if (!fld.isStatic()) { 135 ConstantUtf8 nameCons = (ConstantUtf8) cp.getConstant(nameIdx); 136 ConstantUtf8 typeCons = (ConstantUtf8) cp.getConstant(ntc.getSignatureIndex()); 137 138 if (alreadyReported.contains(nameCons.getBytes())) 139 return; 140 alreadyReported.add(nameCons.getBytes()); 141 bugReporter.reportBug(new BugInstance(this, 142 STRUTS_ACTION_NAME.equals(mtClassName) ? "MTIA_SUSPECT_STRUTS_INSTANCE_FIELD" : "MTIA_SUSPECT_SERVLET_INSTANCE_FIELD", 143 LOW_PRIORITY) 144 .addField(new FieldAnnotation(getClassName(), nameCons.getBytes(), typeCons.getBytes(), false)) 145 .addClass(this).addSourceLine(this) 146 ); 147 } 148 break; 149 } 150 } 151 } 152 } 153 } 154 155 @Override 156 public void sawOpcode(int seen) { 157 if (seen == MONITORENTER) 158 monitorCount++; 159 else if (seen == MONITOREXIT) 160 monitorCount--; 161 162 writingField = ((seen == PUTFIELD) || (seen == PUTFIELD_QUICK) || (seen == PUTFIELD_QUICK_W)); 163 } 164 165 166 167 } 168 | Popular Tags |