]> source.dussan.org Git - poi.git/commitdiff
More cleanups for bug #56814 and some more external entity leaks of #56164
authorUwe Schindler <uschindler@apache.org>
Wed, 13 Aug 2014 22:34:53 +0000 (22:34 +0000)
committerUwe Schindler <uschindler@apache.org>
Wed, 13 Aug 2014 22:34:53 +0000 (22:34 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1617849 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java
src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java
src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java
src/ooxml/java/org/apache/poi/util/DocumentHelper.java
src/ooxml/java/org/apache/poi/util/SAXHelper.java
src/ooxml/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java
src/ooxml/java/org/apache/poi/xssf/extractor/XSSFEventBasedExcelExtractor.java
src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
src/ooxml/java/org/apache/poi/xssf/extractor/XSSFImportFromXML.java
src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java

index 4867810a5c332017115bc3bcc424894d26df020c..043fd632f4123438d0b7f7221ccd50e0f0e5d6eb 100644 (file)
@@ -24,9 +24,9 @@ import java.util.TreeMap;
 
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
+import org.apache.poi.util.DocumentHelper;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-import org.apache.poi.util.SAXHelper;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -311,7 +311,7 @@ public final class PackageRelationshipCollection implements
             throws InvalidFormatException {
         try {
             logger.log(POILogger.DEBUG, "Parsing relationship: " + relPart.getPartName());
-            Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream());
+            Document xmlRelationshipsDoc = DocumentHelper.readDocument(relPart.getInputStream());
 
             // Browse default types
             Element root = xmlRelationshipsDoc.getDocumentElement();
index 7478590a296792b1a16c1dac8bd490117e2eff87..581dabe000c5fa7c375a9e15d066ca498e7c6bfb 100644 (file)
@@ -33,7 +33,6 @@ import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackagePartName;
 import org.apache.poi.openxml4j.opc.PackagingURIHelper;
 import org.apache.poi.util.DocumentHelper;
-import org.apache.poi.util.SAXHelper;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -371,7 +370,7 @@ public abstract class ContentTypeManager {
        private void parseContentTypesFile(InputStream in)
                        throws InvalidFormatException {
                try {
-                       Document xmlContentTypetDoc = SAXHelper.readSAXDocument(in);
+                       Document xmlContentTypetDoc = DocumentHelper.readDocument(in);
 
                        // Default content types
                        NodeList defaultTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagName(DEFAULT_TAG_NAME);
index b4e3e837233354591172d6387095a24da3dda582..eb94f680e6bae58b25dd98ecbece0839259cc5a7 100644 (file)
@@ -31,7 +31,7 @@ import org.apache.poi.openxml4j.opc.ZipPackage;
 import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
 import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller;
 import org.apache.poi.openxml4j.opc.internal.ZipHelper;
-import org.apache.poi.util.SAXHelper;
+import org.apache.poi.util.DocumentHelper;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -105,7 +105,7 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller {
 
                Document xmlDoc;
                try {
-                       xmlDoc = SAXHelper.readSAXDocument(in);
+                       xmlDoc = DocumentHelper.readDocument(in);
 
                        /* Check OPC compliance */
 
index 22bdd4e0fd2bd2f13639525f7823aeea6c9debf1..9ff6e7fb02ff63eb8826e38c892f561505cb0c8d 100644 (file)
 
 package org.apache.poi.util;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+
 import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -25,20 +29,78 @@ import javax.xml.stream.events.Namespace;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
 
-public class DocumentHelper {
+public final class DocumentHelper {
+    private static POILogger logger = POILogFactory.getLogger(DocumentHelper.class);
+    
+    private DocumentHelper() {}
 
-    private static final DocumentBuilder newDocumentBuilder;
-    static {
+    /**
+     * Creates a new document builder, with sensible defaults
+     */
+    public static synchronized DocumentBuilder newDocumentBuilder() {
         try {
-            newDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+            documentBuilder.setEntityResolver(SAXHelper.IGNORING_ENTITY_RESOLVER);
+            return documentBuilder;
         } catch (ParserConfigurationException e) {
             throw new IllegalStateException("cannot create a DocumentBuilder", e);
         }
     }
 
+    private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+    static {
+        documentBuilderFactory.setNamespaceAware(true);
+        documentBuilderFactory.setValidating(false);
+        trySetSAXFeature(documentBuilderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        trySetXercesSecurityManager(documentBuilderFactory);
+    }
+
+    private static void trySetSAXFeature(DocumentBuilderFactory documentBuilderFactory, String feature, boolean enabled) {
+        try {
+            documentBuilderFactory.setFeature(feature, enabled);
+        } catch (Exception e) {
+            logger.log(POILogger.INFO, "SAX Feature unsupported", feature, e);
+        }
+    }
+    private static void trySetXercesSecurityManager(DocumentBuilderFactory documentBuilderFactory) {
+        // Try built-in JVM one first, standalone if not
+        for (String securityManagerClassName : new String[] {
+                "com.sun.org.apache.xerces.internal.util.SecurityManager",
+                "org.apache.xerces.util.SecurityManager"
+        }) {
+            try {
+                Object mgr = Class.forName(securityManagerClassName).newInstance();
+                Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
+                setLimit.invoke(mgr, 4096);
+                documentBuilderFactory.setAttribute("http://apache.org/xml/properties/security-manager", mgr);
+                // Stop once one can be setup without error
+                return;
+            } catch (Exception e) {
+                logger.log(POILogger.INFO, "SAX Security Manager could not be setup", e);
+            }
+        }
+    }
+
+    /**
+     * Parses the given stream via the default (sensible)
+     * DocumentBuilder
+     * @param inp Stream to read the XML data from
+     * @return the parsed Document 
+     */
+    public static Document readDocument(InputStream inp) throws IOException, SAXException {
+        return newDocumentBuilder().parse(inp);
+    }
+
+    // must only be used to create empty documents, do not use it for parsing!
+    private static final DocumentBuilder documentBuilderSingleton = newDocumentBuilder();
+
+    /**
+     * Creates a new DOM Document
+     */
     public static synchronized Document createDocument() {
-        return newDocumentBuilder.newDocument();
+        return documentBuilderSingleton.newDocument();
     }
 
     /**
index 81049a9a2e7028d29c9d189cefd38ea8cfe72cf4..bbc58e51300d718f567d013710c3f99044889f9f 100644 (file)
 package org.apache.poi.util;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.StringReader;
 import java.lang.reflect.Method;
 
 import javax.xml.XMLConstants;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
 
-import org.w3c.dom.Document;
 import org.xml.sax.EntityResolver;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
 
 
 /**
@@ -39,43 +37,43 @@ import org.xml.sax.SAXException;
 public final class SAXHelper {
     private static POILogger logger = POILogFactory.getLogger(SAXHelper.class);
 
-    private static final EntityResolver IGNORING_ENTITY_RESOLVER = new EntityResolver() {
+    private SAXHelper() {}
+
+    /**
+     * Creates a new SAX XMLReader, with sensible defaults
+     */
+    public static synchronized XMLReader newXMLReader() throws SAXException, ParserConfigurationException {
+        XMLReader xmlReader = saxFactory.newSAXParser().getXMLReader();
+        xmlReader.setEntityResolver(IGNORING_ENTITY_RESOLVER);
+        trySetSAXFeature(xmlReader, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        trySetXercesSecurityManager(xmlReader);
+        return xmlReader;
+    }
+    
+    static final EntityResolver IGNORING_ENTITY_RESOLVER = new EntityResolver() {
         @Override
         public InputSource resolveEntity(String publicId, String systemId)
                 throws SAXException, IOException {
             return new InputSource(new StringReader(""));
         }
     };
-
-    private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+    
+    private static final SAXParserFactory saxFactory;
     static {
-        documentBuilderFactory.setNamespaceAware(true);
-        documentBuilderFactory.setValidating(false);
-        trySetSAXFeature(documentBuilderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
-        trySetXercesSecurityManager(documentBuilderFactory);
-    }
-
-    /**
-     * Creates a new document builder, with sensible defaults
-     */
-    public static synchronized DocumentBuilder getDocumentBuilder() {
-        try {
-            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
-            documentBuilder.setEntityResolver(IGNORING_ENTITY_RESOLVER);
-            return documentBuilder;
-        } catch (ParserConfigurationException e) {
-            throw new IllegalStateException("cannot create a DocumentBuilder", e);
-        }
+        saxFactory = SAXParserFactory.newInstance();
+        saxFactory.setValidating(false);
+        saxFactory.setNamespaceAware(true);
     }
-
-    private static void trySetSAXFeature(DocumentBuilderFactory documentBuilderFactory, String feature, boolean enabled) {
+            
+    private static void trySetSAXFeature(XMLReader xmlReader, String feature, boolean enabled) {
         try {
-            documentBuilderFactory.setFeature(feature, enabled);
+            xmlReader.setFeature(feature, enabled);
         } catch (Exception e) {
             logger.log(POILogger.INFO, "SAX Feature unsupported", feature, e);
         }
     }
-    private static void trySetXercesSecurityManager(DocumentBuilderFactory documentBuilderFactory) {
+    
+    private static void trySetXercesSecurityManager(XMLReader xmlReader) {
         // Try built-in JVM one first, standalone if not
         for (String securityManagerClassName : new String[] {
                 "com.sun.org.apache.xerces.internal.util.SecurityManager",
@@ -85,7 +83,7 @@ public final class SAXHelper {
                 Object mgr = Class.forName(securityManagerClassName).newInstance();
                 Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
                 setLimit.invoke(mgr, 4096);
-                documentBuilderFactory.setAttribute("http://apache.org/xml/properties/security-manager", mgr);
+                xmlReader.setProperty("http://apache.org/xml/properties/security-manager", mgr);
                 // Stop once one can be setup without error
                 return;
             } catch (Exception e) {
@@ -93,14 +91,4 @@ public final class SAXHelper {
             }
         }
     }
-
-    /**
-     * Parses the given stream via the default (sensible)
-     * SAX Reader
-     * @param inp Stream to read the XML data from
-     * @return the SAX processed Document 
-     */
-    public static Document readSAXDocument(InputStream inp) throws IOException, SAXException {
-        return getDocumentBuilder().parse(inp);
-    }
 }
index a8973dd32e0488504bfe7ff38a78fb29fea277f6..5263473bcacf6c03a83d647c438a248d3e1a5cec 100644 (file)
@@ -22,12 +22,11 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.util.SAXHelper;
 import org.apache.poi.xssf.usermodel.XSSFRelation;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
@@ -134,10 +133,8 @@ public class ReadOnlySharedStringsTable extends DefaultHandler {
      */
     public void readFrom(InputStream is) throws IOException, SAXException {
         InputSource sheetSource = new InputSource(is);
-        SAXParserFactory saxFactory = SAXParserFactory.newInstance();
         try {
-           SAXParser saxParser = saxFactory.newSAXParser();
-           XMLReader sheetParser = saxParser.getXMLReader();
+           XMLReader sheetParser = SAXHelper.newXMLReader();
            sheetParser.setContentHandler(this);
            sheetParser.parse(sheetSource);
         } catch(ParserConfigurationException e) {
index b70c4abb34150b00dfc626e9be8423a364c13244..c52bed687d33dd3bb18b0fe3b857bc460657c0ae 100644 (file)
@@ -24,8 +24,6 @@ import java.util.Locale;
 import java.util.Map;
 
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.poi.POIXMLProperties;
 import org.apache.poi.POIXMLProperties.CoreProperties;
@@ -35,6 +33,7 @@ import org.apache.poi.POIXMLTextExtractor;
 import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.util.SAXHelper;
 import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
 import org.apache.poi.xssf.eventusermodel.XSSFReader;
 import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
@@ -174,10 +173,8 @@ public class XSSFEventBasedExcelExtractor extends POIXMLTextExtractor
        }
       
        InputSource sheetSource = new InputSource(sheetInputStream);
-       SAXParserFactory saxFactory = SAXParserFactory.newInstance();
        try {
-          SAXParser saxParser = saxFactory.newSAXParser();
-          XMLReader sheetParser = saxParser.getXMLReader();
+          XMLReader sheetParser = SAXHelper.newXMLReader();
           ContentHandler handler = new XSSFSheetXMLHandler(
                 styles, comments, strings, sheetContentsExtractor, formatter, formulasNotResults);
           sheetParser.setContentHandler(handler);
index e9b75e53650db6a1c2d16d1cd5bbe614f57ac119..90b89e36bf9e17ba906e0e9edd48dde007faa0cf 100644 (file)
@@ -28,8 +28,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
@@ -45,7 +43,7 @@ import javax.xml.validation.Validator;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.util.XMLHelper;
+import org.apache.poi.util.DocumentHelper;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFMap;
 import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -106,15 +104,6 @@ public class XSSFExportToXml implements Comparator<String>{
         exportToXML(os, "UTF-8", validate);
     }
 
-    private Document getEmptyDocument() throws ParserConfigurationException{
-
-        DocumentBuilderFactory dbfac = XMLHelper.getDocumentBuilderFactory();
-        DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
-        Document doc = docBuilder.newDocument();
-
-        return doc;
-    }
-
     /**
      * Exports the data in an XML stream
      *
@@ -132,7 +121,7 @@ public class XSSFExportToXml implements Comparator<String>{
 
         String rootElement = map.getCtMap().getRootElement();
 
-        Document doc = getEmptyDocument();
+        Document doc = DocumentHelper.createDocument();
 
         Element root = null;
 
index 945f1677ca8df8542f4c9f0e1653ffe668635283..534ef0d83ee5aeae3e372f4b37162eb2a5c31ce0 100644 (file)
@@ -24,16 +24,15 @@ import java.util.List;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
+import org.apache.poi.util.DocumentHelper;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFMap;
 import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -76,11 +75,9 @@ public class XSSFImportFromXML {
      * @throws ParserConfigurationException if there are problems with XML parser configuration
      * @throws IOException  if there are problems reading the input string
      */
-    public void importFromXML(String xmlInputString) throws SAXException, XPathExpressionException, ParserConfigurationException, IOException {
+    public void importFromXML(String xmlInputString) throws SAXException, XPathExpressionException, IOException {
 
-        DocumentBuilderFactory factory = XMLHelper.getDocumentBuilderFactory();
-        factory.setNamespaceAware(true);
-        DocumentBuilder builder = factory.newDocumentBuilder();
+        DocumentBuilder builder = DocumentHelper.newDocumentBuilder();
 
         Document doc = builder.parse(new InputSource(new StringReader(xmlInputString.trim())));
 
index 1c64fd8629094585d5c28bf9a249d9448d1cc303..c42ce63d4397c15edc70a1f346583ea75552add8 100644 (file)
@@ -42,7 +42,6 @@ import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
 import org.apache.poi.util.DocumentHelper;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-import org.apache.poi.util.SAXHelper;
 import org.apache.poi.util.TempFile;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -218,7 +217,7 @@ public final class TestPackage extends TestCase {
         PackagePartName relName = PackagingURIHelper.createPartName(PackageRelationship.getContainerPartRelationship());
         PackagePart relPart = pkg.getPart(relName);
 
-        Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream());
+        Document xmlRelationshipsDoc = DocumentHelper.readDocument(relPart.getInputStream());
 
         Element root = xmlRelationshipsDoc.getDocumentElement();
         NodeList nodeList = root.getElementsByTagName(PackageRelationship.RELATIONSHIP_TAG_NAME);