Description: CVE-2016-3674: XML external entity injection vulnerability
Origin: backport, https://github.com/x-stream/xstream/commit/c9b121a
                  https://github.com/x-stream/xstream/commit/25c6704
                  https://github.com/x-stream/xstream/commit/87172cf
                  https://github.com/x-stream/xstream/commit/7c77ac0
                  https://github.com/x-stream/xstream/commit/7183131
                  https://github.com/x-stream/xstream/commit/812a0fa
                  https://github.com/x-stream/xstream/commit/6438b65
Bug: https://github.com/x-stream/xstream/issues/25
Bug-Debian: https://bugs.debian.org/819455
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java
@@ -62,7 +62,9 @@
     }
 
     protected XMLInputFactory createInputFactory() {
-        return new MXParserFactory();
+        XMLInputFactory instance = new MXParserFactory();
+        instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+        return instance;
     }
 
     protected XMLOutputFactory createOutputFactory() {
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java
@@ -26,6 +26,7 @@
 import org.dom4j.io.OutputFormat;
 import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
+import org.xml.sax.SAXException;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -89,8 +90,7 @@
 
     public HierarchicalStreamReader createReader(Reader text) {
         try {
-            SAXReader reader = new SAXReader();
-            Document document = reader.read(text);
+            Document document = createReader().read(text);
             return new Dom4JReader(document, getNameCoder());
         } catch (DocumentException e) {
             throw new StreamException(e);
@@ -99,8 +99,7 @@
 
     public HierarchicalStreamReader createReader(InputStream in) {
         try {
-            SAXReader reader = new SAXReader();
-            Document document = reader.read(in);
+            Document document = createReader().read(in);
             return new Dom4JReader(document, getNameCoder());
         } catch (DocumentException e) {
             throw new StreamException(e);
@@ -112,8 +111,7 @@
      */
     public HierarchicalStreamReader createReader(URL in) {
         try {
-            SAXReader reader = new SAXReader();
-            Document document = reader.read(in);
+            Document document = createReader().read(in);
             return new Dom4JReader(document, getNameCoder());
         } catch (DocumentException e) {
             throw new StreamException(e);
@@ -125,8 +123,7 @@
      */
     public HierarchicalStreamReader createReader(File in) {
         try {
-            SAXReader reader = new SAXReader();
-            Document document = reader.read(in);
+            Document document = createReader().read(in);
             return new Dom4JReader(document, getNameCoder());
         } catch (DocumentException e) {
             throw new StreamException(e);
@@ -148,4 +145,21 @@
         final Writer writer = new OutputStreamWriter(out);
         return createWriter(writer);
     }
+
+    /**
+     * Create and initialize the SAX reader.
+     *
+     * @return the SAX reader instance.
+     * @throws DocumentException if DOCTYPE processing cannot be disabled
+     * @since upcoming
+     */
+    protected SAXReader createReader() throws DocumentException {
+        SAXReader reader = new SAXReader();
+        try {
+            reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        } catch (SAXException e) {
+            throw new DocumentException("Cannot disable DOCTYPE processing", e);
+        }
+        return reader;
+    }
 }
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/DomDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/DomDriver.java
@@ -39,7 +39,7 @@
 public class DomDriver extends AbstractXmlDriver {
 
     private final String encoding;
-    private final DocumentBuilderFactory documentBuilderFactory;
+    private DocumentBuilderFactory documentBuilderFactory;
 
     /**
      * Construct a DomDriver.
@@ -61,7 +61,6 @@
      */
     public DomDriver(String encoding, NameCoder nameCoder) {
         super(nameCoder);
-        documentBuilderFactory = DocumentBuilderFactory.newInstance();
         this.encoding = encoding;
     }
 
@@ -91,6 +90,13 @@
 
     private HierarchicalStreamReader createReader(InputSource source) {
         try {
+            if (documentBuilderFactory == null) {
+                synchronized (this) {
+                    if (documentBuilderFactory == null) {
+                        documentBuilderFactory = createDocumentBuilderFactory();
+                    }
+                }
+            }
             DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
             if (encoding != null) {
                 source.setEncoding(encoding);
@@ -121,4 +127,20 @@
             throw new StreamException(e);
         }
     }
+
+    /**
+     * Create the DocumentBuilderFactory instance.
+     *
+     * @return the new instance
+     * @since upcoming
+     */
+    protected DocumentBuilderFactory createDocumentBuilderFactory() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        try {
+            factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        } catch (ParserConfigurationException e) {
+            throw new StreamException(e);
+        }
+        return factory;
+    }
 }
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java
@@ -47,7 +47,7 @@
 
     public HierarchicalStreamReader createReader(Reader reader) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(reader);
             return new JDom2Reader(document, getNameCoder());
         } catch (IOException e) {
@@ -59,7 +59,7 @@
 
     public HierarchicalStreamReader createReader(InputStream in) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(in);
             return new JDom2Reader(document, getNameCoder());
         } catch (IOException e) {
@@ -71,7 +71,7 @@
 
     public HierarchicalStreamReader createReader(URL in) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(in);
             return new JDom2Reader(document, getNameCoder());
         } catch (IOException e) {
@@ -83,7 +83,7 @@
 
     public HierarchicalStreamReader createReader(File in) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(in);
             return new JDom2Reader(document, getNameCoder());
         } catch (IOException e) {
@@ -100,5 +100,17 @@
     public HierarchicalStreamWriter createWriter(OutputStream out) {
         return new PrettyPrintWriter(new OutputStreamWriter(out));
     }
+
+    /**
+     * Create and initialize the SAX builder.
+     *
+     * @return the SAX builder instance.
+     * @since upcoming
+     */
+    protected SAXBuilder createBuilder() {
+        SAXBuilder builder = new SAXBuilder();
+        builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        return builder;
+    }
 }
 
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java
@@ -55,7 +55,7 @@
 
     public HierarchicalStreamReader createReader(Reader reader) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(reader);
             return new JDomReader(document, getNameCoder());
         } catch (IOException e) {
@@ -67,7 +67,7 @@
 
     public HierarchicalStreamReader createReader(InputStream in) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(in);
             return new JDomReader(document, getNameCoder());
         } catch (IOException e) {
@@ -79,7 +79,7 @@
 
     public HierarchicalStreamReader createReader(URL in) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(in);
             return new JDomReader(document, getNameCoder());
         } catch (IOException e) {
@@ -91,7 +91,7 @@
 
     public HierarchicalStreamReader createReader(File in) {
         try {
-            SAXBuilder builder = new SAXBuilder();
+            SAXBuilder builder = createBuilder();
             Document document = builder.build(in);
             return new JDomReader(document, getNameCoder());
         } catch (IOException e) {
@@ -109,5 +109,17 @@
         return new PrettyPrintWriter(new OutputStreamWriter(out));
     }
 
+    /**
+     * Create and initialize the SAX builder.
+     *
+     * @return the SAX builder instance.
+     * @since upcoming
+     */
+    protected SAXBuilder createBuilder() {
+        SAXBuilder builder = new SAXBuilder();
+        builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        return builder;
+    }
+
 }
 
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/SjsxpDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/SjsxpDriver.java
@@ -58,7 +58,9 @@
     protected XMLInputFactory createInputFactory() {
         Exception exception = null;
         try {
-            return (XMLInputFactory)Class.forName("com.sun.xml.internal.stream.XMLInputFactoryImpl").newInstance();
+            XMLInputFactory instance = (XMLInputFactory)Class.forName("com.sun.xml.internal.stream.XMLInputFactoryImpl").newInstance();
+            instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+            return instance;
         } catch (InstantiationException e) {
             exception = e;
         } catch (IllegalAccessException e) {
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/StandardStaxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/StandardStaxDriver.java
@@ -75,7 +75,9 @@
         try {
             Class staxInputFactory = JVM.getStaxInputFactory();
             if (staxInputFactory != null) {
-                return (XMLInputFactory)staxInputFactory.newInstance();
+                XMLInputFactory instance = (XMLInputFactory)staxInputFactory.newInstance();
+                instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+                return instance;
             } else {
                 throw new StreamException("Java runtime has no standard XMLInputFactory implementation.", exception);
             }
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/StaxDriver.java
@@ -238,7 +238,9 @@
      * @since 1.4
      */
     protected XMLInputFactory createInputFactory() {
-        return XMLInputFactory.newInstance();
+        XMLInputFactory instance = XMLInputFactory.newInstance();
+        instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+        return instance;
     }
 
     /**
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java
@@ -62,7 +62,9 @@
     }
 
     protected XMLInputFactory createInputFactory() {
-        return new WstxInputFactory();
+        XMLInputFactory instance = new WstxInputFactory();
+        instance.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+        return instance;
     }
 
     protected XMLOutputFactory createOutputFactory() {
--- a/xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java
+++ b/xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java
@@ -79,7 +79,7 @@
 
     public HierarchicalStreamReader createReader(Reader text) {
         try {
-            Document document = builder.build(text);
+            Document document = getBuilder().build(text);
             return new XomReader(document, getNameCoder());
         } catch (ValidityException e) {
             throw new StreamException(e);
@@ -92,7 +92,7 @@
 
     public HierarchicalStreamReader createReader(InputStream in) {
         try {
-            Document document = builder.build(in);
+            Document document = getBuilder().build(in);
             return new XomReader(document, getNameCoder());
         } catch (ValidityException e) {
             throw new StreamException(e);
@@ -105,7 +105,7 @@
 
     public HierarchicalStreamReader createReader(URL in) {
         try {
-            Document document = builder.build(in.toExternalForm());
+            Document document = getBuilder().build(in.toExternalForm());
             return new XomReader(document, getNameCoder());
         } catch (ValidityException e) {
             throw new StreamException(e);
@@ -118,7 +118,7 @@
 
     public HierarchicalStreamReader createReader(File in) {
         try {
-            Document document = builder.build(in);
+            Document document = getBuilder().build(in);
             return new XomReader(document, getNameCoder());
         } catch (ValidityException e) {
             throw new StreamException(e);
