From 63733c48052db1c4dd1bf7518e5497023746ad19 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 28 Apr 2014 00:27:04 +0200 Subject: [PATCH] AbstractMarshaller avoids SAXSource workaround when processExternalEntities=true Issue: SPR-11737 (cherry picked from commit 93d13cf) (cherry picked from commit 4196e6c) --- .../oxm/jaxb/Jaxb2Marshaller.java | 6 +- .../oxm/support/AbstractMarshaller.java | 59 +++++++------------ .../oxm/xstream/XStreamMarshaller.java | 14 +++-- 3 files changed, 32 insertions(+), 47 deletions(-) diff --git a/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java b/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java index 93fa1a4d1fb..ae9a0af5ee4 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java @@ -401,7 +401,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi } /** - * @return the configured value for whether XML external entities are allowed. + * Returns the configured value for whether XML external entities are allowed. */ public boolean isProcessExternalEntities() { return this.processExternalEntities; @@ -806,9 +806,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi if (xmlReader == null) { xmlReader = XMLReaderFactory.createXMLReader(); } - xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", - this.processExternalEntities); - + xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities()); return new SAXSource(xmlReader, inputSource); } catch (SAXException ex) { diff --git a/spring-oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java b/spring-oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java index 7dd4443b2f1..8ab74248603 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java @@ -58,8 +58,8 @@ import org.springframework.util.xml.StaxUtils; /** * Abstract implementation of the {@code Marshaller} and {@code Unmarshaller} interface. - * This implementation inspects the given {@code Source} or {@code Result}, and defers - * further handling to overridable template methods. + * This implementation inspects the given {@code Source} or {@code Result}, and + * delegates further handling to overridable template methods. * * @author Arjen Poutsma * @author Juergen Hoeller @@ -162,6 +162,7 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller { /** * Determine the default encoding to use for marshalling or unmarshalling from * a byte stream, or {@code null} if none. + *

The default implementation returns {@code null}. */ protected String getDefaultEncoding() { return null; @@ -315,7 +316,7 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller { return unmarshalSaxSource((SAXSource) source); } else if (source instanceof StreamSource) { - return unmarshalStreamSourceNoExternalEntitities((StreamSource) source); + return unmarshalStreamSource((StreamSource) source); } else { throw new IllegalArgumentException("Unknown Source type: " + source.getClass()); @@ -388,41 +389,9 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller { return unmarshalSaxReader(saxSource.getXMLReader(), saxSource.getInputSource()); } - /** - * Template method for handling {@code StreamSource}s with protection against - * the XML External Entity (XXE) processing vulnerability taking into account - * the value of the {@link #setProcessExternalEntities(boolean)} property. - *

The default implementation wraps the StreamSource as a SAXSource and delegates - * to {@link #unmarshalSaxSource(javax.xml.transform.sax.SAXSource)}. - * @param streamSource the {@code StreamSource} - * @return the object graph - * @throws IOException if an I/O exception occurs - * @throws XmlMappingException if the given source cannot be mapped to an object - * @see XML_External_Entity_(XXE)_Processing - */ - protected Object unmarshalStreamSourceNoExternalEntitities(StreamSource streamSource) - throws XmlMappingException, IOException { - - InputSource inputSource; - if (streamSource.getInputStream() != null) { - inputSource = new InputSource(streamSource.getInputStream()); - inputSource.setEncoding(getDefaultEncoding()); - } - else if (streamSource.getReader() != null) { - inputSource = new InputSource(streamSource.getReader()); - } - else { - inputSource = new InputSource(streamSource.getSystemId()); - } - return unmarshalSaxSource(new SAXSource(inputSource)); - } - /** * Template method for handling {@code StreamSource}s. - *

This implementation defers to {@code unmarshalInputStream} or {@code unmarshalReader}. - *

As of Spring 3.2.8, this method is no longer invoked from - * {@link #unmarshal(javax.xml.transform.Source)}. The method invoked instead is - * {@link #unmarshalStreamSourceNoExternalEntitities(javax.xml.transform.stream.StreamSource)}. + *

This implementation delegates to {@code unmarshalInputStream} or {@code unmarshalReader}. * @param streamSource the {@code StreamSource} * @return the object graph * @throws IOException if an I/O exception occurs @@ -430,13 +399,25 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller { */ protected Object unmarshalStreamSource(StreamSource streamSource) throws XmlMappingException, IOException { if (streamSource.getInputStream() != null) { - return unmarshalInputStream(streamSource.getInputStream()); + if (isProcessExternalEntities()) { + return unmarshalInputStream(streamSource.getInputStream()); + } + else { + InputSource inputSource = new InputSource(streamSource.getInputStream()); + inputSource.setEncoding(getDefaultEncoding()); + return unmarshalSaxSource(new SAXSource(inputSource)); + } } else if (streamSource.getReader() != null) { - return unmarshalReader(streamSource.getReader()); + if (isProcessExternalEntities()) { + return unmarshalReader(streamSource.getReader()); + } + else { + return unmarshalSaxSource(new SAXSource(new InputSource(streamSource.getReader()))); + } } else { - throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader"); + return unmarshalSaxSource(new SAXSource(new InputSource(streamSource.getSystemId()))); } } diff --git a/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java b/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java index 14b114efffb..2f4cdf8b3b8 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java @@ -731,10 +731,16 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin // Unmarshalling @Override - protected Object unmarshalStreamSourceNoExternalEntitities(StreamSource streamSource) - throws XmlMappingException, IOException { - - return super.unmarshalStreamSource(streamSource); + protected Object unmarshalStreamSource(StreamSource streamSource) throws XmlMappingException, IOException { + if (streamSource.getInputStream() != null) { + return unmarshalInputStream(streamSource.getInputStream()); + } + else if (streamSource.getReader() != null) { + return unmarshalReader(streamSource.getReader()); + } + else { + throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader"); + } } @Override