[Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect OrphanedDOMNode.java,NONE,1.1
Brought to you by:
dbrosius
|
From: Dave B. <dbr...@us...> - 2005-12-23 05:23:36
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22247/src/com/mebigfatguy/fbcontrib/detect Added Files: OrphanedDOMNode.java Log Message: initial checkin: new ODN detector --- NEW FILE: OrphanedDOMNode.java --- /* * fb-contrib - Auxilliary detectors for Java programs * Copyright (C) 2005 Dave Brosius * * 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 java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.bcel.classfile.Code; import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.BytecodeScanningDetector; import edu.umd.cs.findbugs.OpcodeStack; import edu.umd.cs.findbugs.StatelessDetector; public class OrphanedDOMNode extends BytecodeScanningDetector implements StatelessDetector { private static final Set<String> domCreationMethods = new HashSet<String>(); private static final Set<String> domAppendMethods = new HashSet<String>(); static { domCreationMethods.add("createAttribute:(Ljava/lang/String;)Lorg/w3c/dom/Attr;"); domCreationMethods.add("createAttributeNS:(Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Attr;"); domCreationMethods.add("createCDATASection:(Ljava/lang/String;)Lorg/w3c/dom/CDATASection;"); domCreationMethods.add("createComment:(Ljava/lang/String;)Lorg/w3c/dom/Comment;"); domCreationMethods.add("createElement:(Ljava/lang/String;)Lorg/w3c/dom/Element;"); domCreationMethods.add("createElementNS:(Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Element;"); domCreationMethods.add("createProcessingInstruction:(Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/ProcessingInstruction;"); domCreationMethods.add("createTextNode:(Ljava/lang/String;)Lorg/w3c/dom/Text;"); domAppendMethods.add("appendChild:(Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;"); domAppendMethods.add("setAttributeNode:(Lorg/w3c/dom/Attr;)Lorg/w3c/dom/Attr;"); domAppendMethods.add("setAttributeNodeNS:(Lorg/w3c/dom/Attr;)Lorg/w3c/dom/Attr;"); } private BugReporter bugReporter; private OpcodeStack stack = new OpcodeStack(); private Map<OpcodeStack.Item, Integer> nodeCreations = new HashMap<OpcodeStack.Item, Integer>(); private Map<Integer, Integer> nodeStores = new HashMap<Integer, Integer>(); /** * constructs a ODN detector given the reporter to report bugs on * @param bugReporter the sync of bug reports */ public OrphanedDOMNode(BugReporter bugReporter) { this.bugReporter = bugReporter; } /** * clone this detector so that it can be a StatelessDetector * * @return a clone of this object */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } /** * implements the visitor to clear the opcode stack for the next code * * @param obj the context object for the currently parsed code block */ public void visitCode(Code obj) { stack.resetForMethodEntry(this); nodeCreations.clear(); nodeStores.clear(); super.visitCode(obj); Set<Integer> reportedPCs = new HashSet<Integer>(); for (Integer pc : nodeCreations.values()) { if (!reportedPCs.contains(pc)) { bugReporter.reportBug(new BugInstance(this, "ODN_ORPHANED_DOM_NODE", NORMAL_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this, pc.intValue())); reportedPCs.add(pc); } } for (Integer pc : nodeStores.values()) { if (!reportedPCs.contains(pc)) { bugReporter.reportBug(new BugInstance(this, "ODN_ORPHANED_DOM_NODE", NORMAL_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this, pc.intValue())); reportedPCs.add(pc); } } } /** * implements the visitor to find DOM based nodes that are allocated but not appended to * an existing node (or returned). * * @param seen the currently parsed opcode */ public void sawOpcode(int seen) { boolean sawCreate = false; Integer itemPC = null; try { if (seen == INVOKEINTERFACE) { String className = getClassConstantOperand(); String methodInfo = getNameConstantOperand() + ":" + getSigConstantOperand(); if ("org/w3c/dom/Document".equals(className)) { if (domCreationMethods.contains(methodInfo)) { sawCreate = true; itemPC = new Integer(getPC()); } } if (!sawCreate) { if (domAppendMethods.contains(methodInfo)) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); int reg = itm.getRegisterNumber(); nodeCreations.remove(itm); nodeStores.remove(reg); } } } } else if ((seen == ASTORE) || ((seen >= ASTORE_0) && seen <= ASTORE_3)) { Integer pc = findDOMNodeCreationPoint(0); int reg; if (seen == ASTORE) reg = getRegisterOperand(); else reg = seen - ASTORE_0; if (pc != null) nodeStores.put(new Integer(reg), pc); else nodeStores.remove(new Integer(reg)); } else if (seen == PUTFIELD) { //Stores to member variables are assumed ok findDOMNodeCreationPoint(0); } else if ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) { int reg; if (seen == ALOAD) reg = getRegisterOperand(); else reg = seen - ALOAD_0; itemPC = nodeStores.get(new Integer(reg)); if (itemPC != null) sawCreate = true; } else if (seen == ARETURN) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); int reg = itm.getRegisterNumber(); nodeCreations.remove(itm); nodeStores.remove(new Integer(reg)); } } } finally { stack.sawOpcode(this, seen); if (sawCreate) { if (stack.getStackDepth() > 0) nodeCreations.put(stack.getStackItem(0), itemPC); } } } /** * returns the pc where this DOM Node was created, or null if this isn't a DOM node that was created * * @param index the index into the stack of the item to be checked * * @return the pc where this NODE was created, or null */ private Integer findDOMNodeCreationPoint(int index) { if (stack.getStackDepth() > index) return nodeCreations.remove(stack.getStackItem(index)); return null; } } |