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.JavaClass; 28 29 public class XMLFactoryBypass extends BytecodeScanningDetector { 30 private BugReporter bugReporter; 31 private static final Set<String > xmlInterfaces = new HashSet<String >() 32 { 33 static final long serialVersionUID = -9117982073509840017L; 34 { 35 add("javax.xml.parsers.DocumentBuilder"); 36 add("org.w3c.dom.Document"); 37 add("javax.xml.parsers.SAXParser"); 38 add("org.xml.sax.XMLReader"); 39 add("org.xml.sax.XMLFilter"); 40 add("javax.xml.transform.Transformer"); 41 add("org.w3c.dom.Attr"); 42 add("org.w3c.dom.CDATASection"); 43 add("org.w3c.dom.Comment"); 44 add("org.w3c.dom.Element"); 45 add("org.w3c.dom.Text"); 46 } 47 }; 48 private final Set<String > rejectedXMLClasses = new HashSet<String >(); 49 private JavaClass curClass; 50 51 public XMLFactoryBypass(BugReporter bugReporter) { 52 this.bugReporter = bugReporter; 53 } 54 55 @Override 56 public void visitClassContext(ClassContext classContext) { 57 curClass = classContext.getJavaClass(); 58 super.visitClassContext(classContext); 59 } 60 61 @Override 62 public void sawOpcode(int seen) { 63 try { 64 if (seen == INVOKESPECIAL) { 65 String newClsName = getClassConstantOperand(); 66 if (rejectedXMLClasses.contains(newClsName)) 67 return; 68 rejectedXMLClasses.add(newClsName); 69 70 if (newClsName.startsWith("java/") || newClsName.startsWith("javax/")) 71 return; 72 73 if (newClsName.endsWith("Adapter")) 74 return; 75 76 if (!getNameConstantOperand().equals("<init>")) 77 return; 78 79 String invokerClsName = this.getClassName(); 80 if (samePackageBase(invokerClsName, newClsName)) 81 return; 82 83 JavaClass newCls = Repository.lookupClass(getDottedClassConstantOperand()); 84 85 JavaClass superCls = curClass.getSuperClass(); 86 if (superCls.getClassName().equals(newClsName.replace('/', '.'))) 87 return; 88 89 JavaClass[] infs = newCls.getAllInterfaces(); 90 for (JavaClass inf : infs) { 91 if (xmlInterfaces.contains(inf.getClassName())) { 92 bugReporter.reportBug(new BugInstance(this, "XFB_XML_FACTORY_BYPASS", LOW_PRIORITY) 93 .addClassAndMethod(this) 94 .addSourceLine(this)); 95 rejectedXMLClasses.remove(newClsName); 96 } 97 } 98 } 99 } catch (ClassNotFoundException cnfe) { 100 bugReporter.reportMissingClass(cnfe); 101 } 102 } 103 104 public boolean samePackageBase(String invokerClsName, String newClsName) 105 { 106 String [] invokerParts = invokerClsName.split("/"); 107 String [] newClsParts = newClsName.split("/"); 108 109 if (newClsParts.length < 3) 110 return false; 111 if (invokerParts.length < 3) 112 return false; 113 114 if (!invokerParts[0].equals(newClsParts[0])) 115 return false; 116 117 return invokerParts[1].equals(newClsParts[1]); 118 } 119 } 120 | Popular Tags |