Skip to content

Commit

Permalink
Disable URL resolution in DTD declarations
Browse files Browse the repository at this point in the history
Issue: SPR-11768
  • Loading branch information
rstoyanchev committed May 20, 2014
1 parent 61b47ba commit 8e096ae
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
Expand Down Expand Up @@ -72,6 +73,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
Expand Down Expand Up @@ -806,7 +808,11 @@ else if (streamSource.getReader() != null) {
if (xmlReader == null) {
xmlReader = XMLReaderFactory.createXMLReader();
}
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
String name = "http://xml.org/sax/features/external-general-entities";
xmlReader.setFeature(name, isProcessExternalEntities());
if (!isProcessExternalEntities()) {
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
}
return new SAXSource(xmlReader, inputSource);
}
catch (SAXException ex) {
Expand Down Expand Up @@ -1019,4 +1025,11 @@ public String getName() {
}
}

private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
Expand All @@ -43,6 +44,7 @@
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
Expand Down Expand Up @@ -156,6 +158,9 @@ protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
protected XMLReader createXmlReader() throws SAXException {
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
if (!isProcessExternalEntities()) {
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
}
return xmlReader;
}

Expand Down Expand Up @@ -545,4 +550,12 @@ protected abstract Object unmarshalInputStream(InputStream inputStream)
protected abstract Object unmarshalReader(Reader reader)
throws XmlMappingException, IOException;


private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.springframework.http.converter.xml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
Expand All @@ -32,6 +33,7 @@
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Result;
Expand Down Expand Up @@ -230,7 +232,16 @@ protected void writeToResult(T t, HttpHeaders headers, Result result) throws IOE
protected XMLInputFactory createXmlInputFactory() {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
inputFactory.setXMLResolver(NO_OP_XML_RESOLVER);
return inputFactory;
}


private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
@Override
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
return new ByteArrayInputStream(new byte[0]);
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.http.converter.xml;

import java.io.IOException;
import java.io.StringReader;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.MarshalException;
Expand All @@ -38,6 +39,7 @@
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.ClassUtils;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
Expand Down Expand Up @@ -67,6 +69,10 @@ public void setProcessExternalEntities(boolean processExternalEntities) {
this.processExternalEntities = processExternalEntities;
}

public boolean isProcessExternalEntities() {
return this.processExternalEntities;
}

@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return (clazz.isAnnotationPresent(XmlRootElement.class) || clazz.isAnnotationPresent(XmlType.class)) &&
Expand Down Expand Up @@ -113,7 +119,10 @@ protected Source processSource(Source source) {
try {
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
String featureName = "http://xml.org/sax/features/external-general-entities";
xmlReader.setFeature(featureName, this.processExternalEntities);
xmlReader.setFeature(featureName, isProcessExternalEntities());
if (!isProcessExternalEntities()) {
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
}
return new SAXSource(xmlReader, inputSource);
}
catch (SAXException ex) {
Expand Down Expand Up @@ -148,4 +157,12 @@ private void setCharset(MediaType contentType, Marshaller marshaller) throws Pro
}
}


private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Result;
Expand All @@ -39,6 +41,7 @@
import javax.xml.transform.stream.StreamSource;

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;
Expand Down Expand Up @@ -136,8 +139,11 @@ private DOMSource readDOMSource(InputStream body) throws IOException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setFeature(
"http://xml.org/sax/features/external-general-entities", this.processExternalEntities);
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
if (!isProcessExternalEntities()) {
documentBuilder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
}
Document document = documentBuilder.parse(body);
return new DOMSource(document);
}
Expand All @@ -152,9 +158,11 @@ private DOMSource readDOMSource(InputStream body) throws IOException {
private SAXSource readSAXSource(InputStream body) throws IOException {
try {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature(
"http://xml.org/sax/features/external-general-entities", this.processExternalEntities);
reader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
byte[] bytes = StreamUtils.copyToByteArray(body);
if (!isProcessExternalEntities()) {
reader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
}
return new SAXSource(reader, new InputSource(new ByteArrayInputStream(bytes)));
}
catch (SAXException ex) {
Expand All @@ -165,7 +173,10 @@ private SAXSource readSAXSource(InputStream body) throws IOException {
private Source readStAXSource(InputStream body) {
try {
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, this.processExternalEntities);
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, isProcessExternalEntities());
if (!isProcessExternalEntities()) {
inputFactory.setXMLResolver(NO_OP_XML_RESOLVER);
}
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(body);
return new StAXSource(streamReader);
}
Expand Down Expand Up @@ -231,4 +242,19 @@ public void write(byte[] b, int off, int len) throws IOException {
}
}


private static final EntityResolver NO_OP_ENTITY_RESOLVER = new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
};

private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
@Override
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
return new ByteArrayInputStream(new byte[0]);
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void readXmlType() throws Exception {
@Test
public void readXmlRootElementExternalEntityDisabled() throws Exception {
Resource external = new ClassPathResource("external.txt", getClass());
String content = "<!DOCTYPE root [" +
String content = "<!DOCTYPE root SYSTEM \"http://192.168.28.42/1.jsp\" [" +
" <!ELEMENT external ANY >\n" +
" <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]>" +
" <rootElement><external>&ext;</external></rootElement>";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void setUp() throws IOException {
converter = new SourceHttpMessageConverter<Source>();
Resource external = new ClassPathResource("external.txt", getClass());

bodyExternal = "<!DOCTYPE root [" +
bodyExternal = "<!DOCTYPE root SYSTEM \"http://192.168.28.42/1.jsp\" [" +
" <!ELEMENT root ANY >\n" +
" <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]><root>&ext;</root>";
}
Expand Down

0 comments on commit 8e096ae

Please sign in to comment.