[libspring-java] 01/02: Upload 3.0.6.RELEASE-6+deb7u2 to wheezy-security
Miguel Landaeta
nomadium at moszumanska.debian.org
Mon Mar 24 21:49:22 UTC 2014
This is an automated email from the git hooks/post-receive script.
nomadium pushed a commit to branch stable-security
in repository libspring-java.
commit 839adf8d0a1fa2d93a876f4dfdacc4c142590b4a
Author: Miguel Landaeta <nomadium at debian.org>
Date: Mon Mar 24 18:10:22 2014 -0300
Upload 3.0.6.RELEASE-6+deb7u2 to wheezy-security
---
debian/changelog | 18 +
debian/patches/CVE-2013-6429.patch | 712 +++++++++++++++++++++++++++++++++++++
debian/patches/CVE-2013-6430.patch | 151 ++++++++
debian/patches/series | 2 +
4 files changed, 883 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index a45a04b..2b27234 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,21 @@
+libspring-java (3.0.6.RELEASE-6+deb7u2) wheezy-security; urgency=high
+
+ * Team upload.
+ * Fix CVE-2013-6429 and CVE-2013-6430. (Closes: #735420)
+ - New patches: CVE-2013-6429.patch and CVE-2013-6430.patch.
+ - Spring MVC's SourceHttpMessageConverter also processed user provided XML
+ and neither disabled XML external entities nor provided an option to
+ disable them. SourceHttpMessageConverter has been modified to provide an
+ option to control the processing of XML external entities and that
+ processing is now disabled by default.
+ - The JavaScriptUtils.javaScriptEscape() method did not escape all
+ characters that are sensitive within either a JS single quoted string, JS
+ double quoted string, or HTML script data context. In most cases this
+ will result in an unexploitable parse error but in some cases it could
+ result in an XSS vulnerability.
+
+ -- Markus Koschany <apo at gambaru.de> Mon, 27 Jan 2014 15:56:41 +0100
+
libspring-java (3.0.6.RELEASE-6+deb7u1) wheezy-security; urgency=high
* Team upload.
diff --git a/debian/patches/CVE-2013-6429.patch b/debian/patches/CVE-2013-6429.patch
new file mode 100644
index 0000000..3334c0e
--- /dev/null
+++ b/debian/patches/CVE-2013-6429.patch
@@ -0,0 +1,712 @@
+From: Markus Koschany <apo at gambaru.de>
+Date: Fri, 24 Jan 2014 16:46:07 +0100
+Subject: CVE-2013-6429
+
+Bug: http://bugs.debian.org/735420
+---
+ .../java/org/springframework/util/StreamUtils.java | 183 ++++++++++++++++++++
+ .../org/springframework/util/xml/StaxUtils.java | 15 +-
+ .../converter/xml/SourceHttpMessageConverter.java | 190 +++++++++++++++++----
+ .../xml/SourceHttpMessageConverterTests.java | 145 +++++++++++++---
+ .../http/converter/xml/external.txt | 1 +
+ 5 files changed, 478 insertions(+), 56 deletions(-)
+ create mode 100644 projects/org.springframework.core/src/main/java/org/springframework/util/StreamUtils.java
+ create mode 100644 projects/org.springframework.web/src/test/resources/org/springframework/http/converter/xml/external.txt
+
+diff --git a/projects/org.springframework.core/src/main/java/org/springframework/util/StreamUtils.java b/projects/org.springframework.core/src/main/java/org/springframework/util/StreamUtils.java
+new file mode 100644
+index 0000000..cc3107d
+--- /dev/null
++++ b/projects/org.springframework.core/src/main/java/org/springframework/util/StreamUtils.java
+@@ -0,0 +1,183 @@
++/*
++ * Copyright 2002-2013 the original author or authors.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package org.springframework.util;
++
++import java.io.ByteArrayOutputStream;
++import java.io.FilterInputStream;
++import java.io.FilterOutputStream;
++import java.io.IOException;
++import java.io.InputStream;
++import java.io.InputStreamReader;
++import java.io.OutputStream;
++import java.io.OutputStreamWriter;
++import java.io.Writer;
++import java.nio.charset.Charset;
++
++
++/**
++ * Simple utility methods for dealing with streams. The copy methods of this class are
++ * similar to those defined in {@link FileCopyUtils} except that all affected streams are
++ * left open when done. All copy methods use a block size of 4096 bytes.
++ *
++ * <p>Mainly for use within the framework, but also useful for application code.
++ *
++ * @author Juergen Hoeller
++ * @author Phillip Webb
++ * @since 3.2.2
++ * @see FileCopyUtils
++ */
++public abstract class StreamUtils {
++
++ public static final int BUFFER_SIZE = 4096;
++
++
++ /**
++ * Copy the contents of the given InputStream into a new byte array.
++ * Leaves the stream open when done.
++ * @param in the stream to copy from
++ * @return the new byte array that has been copied to
++ * @throws IOException in case of I/O errors
++ */
++ public static byte[] copyToByteArray(InputStream in) throws IOException {
++ ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
++ copy(in, out);
++ return out.toByteArray();
++ }
++
++ /**
++ * Copy the contents of the given InputStream into a String.
++ * Leaves the stream open when done.
++ * @param in the InputStream to copy from
++ * @return the String that has been copied to
++ * @throws IOException in case of I/O errors
++ */
++ public static String copyToString(InputStream in, Charset charset) throws IOException {
++ Assert.notNull(in, "No InputStream specified");
++ StringBuilder out = new StringBuilder();
++ InputStreamReader reader = new InputStreamReader(in, charset);
++ char[] buffer = new char[BUFFER_SIZE];
++ int bytesRead = -1;
++ while ((bytesRead = reader.read(buffer)) != -1) {
++ out.append(buffer, 0, bytesRead);
++ }
++ return out.toString();
++ }
++
++ /**
++ * Copy the contents of the given byte array to the given OutputStream.
++ * Leaves the stream open when done.
++ * @param in the byte array to copy from
++ * @param out the OutputStream to copy to
++ * @throws IOException in case of I/O errors
++ */
++ public static void copy(byte[] in, OutputStream out) throws IOException {
++ Assert.notNull(in, "No input byte array specified");
++ Assert.notNull(out, "No OutputStream specified");
++ out.write(in);
++ }
++
++ /**
++ * Copy the contents of the given String to the given output OutputStream.
++ * Leaves the stream open when done.
++ * @param in the String to copy from
++ * @param charset the Charset
++ * @param out the OutputStream to copy to
++ * @throws IOException in case of I/O errors
++ */
++ public static void copy(String in, Charset charset, OutputStream out) throws IOException {
++ Assert.notNull(in, "No input String specified");
++ Assert.notNull(charset, "No charset specified");
++ Assert.notNull(out, "No OutputStream specified");
++ Writer writer = new OutputStreamWriter(out, charset);
++ writer.write(in);
++ writer.flush();
++ }
++
++ /**
++ * Copy the contents of the given InputStream to the given OutputStream.
++ * Leaves both streams open when done.
++ * @param in the InputStream to copy from
++ * @param out the OutputStream to copy to
++ * @return the number of bytes copied
++ * @throws IOException in case of I/O errors
++ */
++ public static int copy(InputStream in, OutputStream out) throws IOException {
++ Assert.notNull(in, "No InputStream specified");
++ Assert.notNull(out, "No OutputStream specified");
++ int byteCount = 0;
++ byte[] buffer = new byte[BUFFER_SIZE];
++ int bytesRead = -1;
++ while ((bytesRead = in.read(buffer)) != -1) {
++ out.write(buffer, 0, bytesRead);
++ byteCount += bytesRead;
++ }
++ out.flush();
++ return byteCount;
++ }
++
++ /**
++ * Returns a variant of the given {@link InputStream} where calling
++ * {@link InputStream#close() close()} has no effect.
++ * @param in the InputStream to decorate
++ * @return a version of the InputStream that ignores calls to close
++ */
++ public static InputStream nonClosing(InputStream in) {
++ Assert.notNull(in, "No InputStream specified");
++ return new NonClosingInputStream(in);
++ }
++
++ /**
++ * Returns a variant of the given {@link OutputStream} where calling
++ * {@link OutputStream#close() close()} has no effect.
++ * @param out the OutputStream to decorate
++ * @return a version of the OutputStream that ignores calls to close
++ */
++ public static OutputStream nonClosing(OutputStream out) {
++ Assert.notNull(out, "No OutputStream specified");
++ return new NonClosingOutputStream(out);
++ }
++
++
++ private static class NonClosingInputStream extends FilterInputStream {
++
++ public NonClosingInputStream(InputStream in) {
++ super(in);
++ }
++
++ @Override
++ public void close() throws IOException {
++ }
++ }
++
++
++ private static class NonClosingOutputStream extends FilterOutputStream {
++
++ public NonClosingOutputStream(OutputStream out) {
++ super(out);
++ }
++
++ @Override
++ public void write(byte[] b, int off, int let) throws IOException {
++ // It is critical that we override this method for performance
++ out.write(b, off, let);
++ }
++
++ @Override
++ public void close() throws IOException {
++ }
++ }
++}
+diff --git a/projects/org.springframework.core/src/main/java/org/springframework/util/xml/StaxUtils.java b/projects/org.springframework.core/src/main/java/org/springframework/util/xml/StaxUtils.java
+index 4bd4a7a..dee73ca 100644
+--- a/projects/org.springframework.core/src/main/java/org/springframework/util/xml/StaxUtils.java
++++ b/projects/org.springframework.core/src/main/java/org/springframework/util/xml/StaxUtils.java
+@@ -113,7 +113,16 @@ public abstract class StaxUtils {
+ * 1.4 {@link StAXSource}; {@code false} otherwise.
+ */
+ public static boolean isStaxSource(Source source) {
+- return (source instanceof StaxSource || (jaxp14Available && Jaxp14StaxHandler.isStaxSource(source)));
++ return ((source instanceof StaxSource) || (jaxp14Available && Jaxp14StaxHandler.isStaxSource(source)));
++ }
++
++ /**
++ * Indicate whether the given class is a StAX Source class.
++ * @return {@code true} if {@code source} is a custom StAX source or JAXP
++ * 1.4 {@link StAXSource} class; {@code false} otherwise.
++ */
++ public static boolean isStaxSourceClass(Class<? extends Source> clazz) {
++ return (StaxSource.class.equals(clazz) || (jaxp14Available && Jaxp14StaxHandler.isStaxSourceClass(clazz)));
+ }
+
+ // Stax Result
+@@ -343,6 +352,10 @@ public abstract class StaxUtils {
+ return source instanceof StAXSource;
+ }
+
++ private static boolean isStaxSourceClass(Class<? extends Source> clazz) {
++ return StAXSource.class.equals(clazz);
++ }
++
+ private static boolean isStaxResult(Result result) {
+ return result instanceof StAXResult;
+ }
+diff --git a/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java b/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
+index 4ba1aac..15b7d8e 100644
+--- a/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
++++ b/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2002-2010 the original author or authors.
++ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+@@ -19,21 +19,40 @@ package org.springframework.http.converter.xml;
+ import java.io.ByteArrayInputStream;
+ import java.io.ByteArrayOutputStream;
+ import java.io.IOException;
++import java.io.InputStream;
++import java.io.OutputStream;
++import javax.xml.parsers.DocumentBuilder;
++import javax.xml.parsers.DocumentBuilderFactory;
++import javax.xml.parsers.ParserConfigurationException;
++import javax.xml.stream.XMLInputFactory;
++import javax.xml.stream.XMLStreamException;
++import javax.xml.stream.XMLStreamReader;
+ import javax.xml.transform.Result;
+ import javax.xml.transform.Source;
+ import javax.xml.transform.TransformerException;
++import javax.xml.transform.TransformerFactory;
+ import javax.xml.transform.dom.DOMResult;
+ import javax.xml.transform.dom.DOMSource;
+ import javax.xml.transform.sax.SAXSource;
+ import javax.xml.transform.stream.StreamResult;
+ import javax.xml.transform.stream.StreamSource;
+
++import org.w3c.dom.Document;
+ import org.xml.sax.InputSource;
++import org.xml.sax.SAXException;
++import org.xml.sax.XMLReader;
++import org.xml.sax.helpers.XMLReaderFactory;
+
+ import org.springframework.http.HttpHeaders;
++import org.springframework.http.HttpInputMessage;
++import org.springframework.http.HttpOutputMessage;
++import org.springframework.http.MediaType;
++import org.springframework.http.converter.AbstractHttpMessageConverter;
+ import org.springframework.http.converter.HttpMessageConversionException;
+ import org.springframework.http.converter.HttpMessageNotReadableException;
+ import org.springframework.http.converter.HttpMessageNotWritableException;
++import org.springframework.util.StreamUtils;
++import org.springframework.util.xml.StaxUtils;
+
+ /**
+ * Implementation of {@link org.springframework.http.converter.HttpMessageConverter}
+@@ -42,55 +61,154 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
+ * @author Arjen Poutsma
+ * @since 3.0
+ */
+-public class SourceHttpMessageConverter<T extends Source> extends AbstractXmlHttpMessageConverter<T> {
++public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMessageConverter<T> {
+
+- @Override
++ private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
++
++ private boolean processExternalEntities = false;
++
++ /**
++ * Sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
++ * to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}.
++ */
++ public SourceHttpMessageConverter() {
++ super(MediaType.APPLICATION_XML, MediaType.TEXT_XML, new MediaType("application", "*+xml"));
++ }
++
++
++ /**
++ * Indicates whether external XML entities are processed when converting
++ * to a Source.
++ * <p>Default is {@code false}, meaning that external entities are not resolved.
++ */
++ public void setProcessExternalEntities(boolean processExternalEntities) {
++ this.processExternalEntities = processExternalEntities;
++ }
++
++ @Override
+ public boolean supports(Class<?> clazz) {
+- return DOMSource.class.equals(clazz) || SAXSource.class.equals(clazz) || StreamSource.class.equals(clazz) ||
+- Source.class.equals(clazz);
++ return DOMSource.class.equals(clazz) || SAXSource.class.equals(clazz)
++ || StreamSource.class.equals(clazz) || Source.class.equals(clazz);
+ }
+
++ @Override
++ protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
++ throws IOException, HttpMessageNotReadableException {
++
++ InputStream body = inputMessage.getBody();
++ if (DOMSource.class.equals(clazz)) {
++ return (T) readDOMSource(body);
++ }
++ else if (StaxUtils.isStaxSourceClass(clazz)) {
++ return (T) readStAXSource(body);
++ }
++ else if (SAXSource.class.equals(clazz)) {
++ return (T) readSAXSource(body);
++ }
++ else if (StreamSource.class.equals(clazz) || Source.class.equals(clazz)) {
++ return (T) readStreamSource(body);
++ }
++ else {
++ throw new HttpMessageConversionException("Could not read class [" + clazz +
++ "]. Only DOMSource, SAXSource, and StreamSource are supported.");
++ }
++ }
++
++ private DOMSource readDOMSource(InputStream body) throws IOException {
++ try {
++ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
++ documentBuilderFactory.setNamespaceAware(true);
++ documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", processExternalEntities);
++ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
++ Document document = documentBuilder.parse(body);
++ return new DOMSource(document);
++ }
++ catch (ParserConfigurationException ex) {
++ throw new HttpMessageNotReadableException("Could not set feature: " + ex.getMessage(), ex);
++ }
++ catch (SAXException ex) {
++ throw new HttpMessageNotReadableException("Could not parse document: " + ex.getMessage(), ex);
++ }
++ }
++
++ private SAXSource readSAXSource(InputStream body) throws IOException {
++ try {
++ XMLReader reader = XMLReaderFactory.createXMLReader();
++ reader.setFeature("http://xml.org/sax/features/external-general-entities", processExternalEntities);
++ byte[] bytes = StreamUtils.copyToByteArray(body);
++ return new SAXSource(reader, new InputSource(new ByteArrayInputStream(bytes)));
++ }
++ catch (SAXException ex) {
++ throw new HttpMessageNotReadableException("Could not parse document: " + ex.getMessage(), ex);
++ }
++ }
++
++ private Source readStAXSource(InputStream body) {
++ try {
++ XMLInputFactory inputFactory = XMLInputFactory.newFactory();
++ inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", processExternalEntities);
++ XMLStreamReader streamReader = inputFactory.createXMLStreamReader(body);
++ return StaxUtils.createStaxSource(streamReader);
++ }
++ catch (XMLStreamException ex) {
++ throw new HttpMessageNotReadableException("Could not parse document: " + ex.getMessage(), ex);
++ }
++ }
++
++ private StreamSource readStreamSource(InputStream body) throws IOException {
++ byte[] bytes = StreamUtils.copyToByteArray(body);
++ return new StreamSource(new ByteArrayInputStream(bytes));
++ }
++
+ @Override
+- @SuppressWarnings("unchecked")
+- protected T readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException {
+- try {
+- if (DOMSource.class.equals(clazz)) {
+- DOMResult domResult = new DOMResult();
+- transform(source, domResult);
+- return (T) new DOMSource(domResult.getNode());
+- }
+- else if (SAXSource.class.equals(clazz)) {
+- ByteArrayInputStream bis = transformToByteArrayInputStream(source);
+- return (T) new SAXSource(new InputSource(bis));
++ protected Long getContentLength(T t, MediaType contentType) {
++ if (t instanceof DOMSource) {
++ try {
++ CountingOutputStream os = new CountingOutputStream();
++ transform(t, new StreamResult(os));
++ return os.count;
+ }
+- else if (StreamSource.class.equals(clazz) || Source.class.equals(clazz)) {
+- ByteArrayInputStream bis = transformToByteArrayInputStream(source);
+- return (T) new StreamSource(bis);
+- }
+- else {
+- throw new HttpMessageConversionException("Could not read class [" + clazz +
+- "]. Only DOMSource, SAXSource, and StreamSource are supported.");
++ catch (TransformerException ex) {
++ // ignore
+ }
+ }
+- catch (TransformerException ex) {
+- throw new HttpMessageNotReadableException("Could not transform from [" + source + "] to [" + clazz + "]",
+- ex);
+- }
+- }
+-
+- private ByteArrayInputStream transformToByteArrayInputStream(Source source) throws TransformerException {
+- ByteArrayOutputStream bos = new ByteArrayOutputStream();
+- transform(source, new StreamResult(bos));
+- return new ByteArrayInputStream(bos.toByteArray());
++ return null;
+ }
+
+- @Override
+- protected void writeToResult(T t, HttpHeaders headers, Result result) throws IOException {
++ @Override
++ protected void writeInternal(T t, HttpOutputMessage outputMessage)
++ throws IOException, HttpMessageNotWritableException {
+ try {
++ Result result = new StreamResult(outputMessage.getBody());
+ transform(t, result);
+ }
+ catch (TransformerException ex) {
+- throw new HttpMessageNotWritableException("Could not transform [" + t + "] to [" + result + "]", ex);
++ throw new HttpMessageNotWritableException("Could not transform [" + t + "] to output message", ex);
++ }
++ }
++
++ private void transform(Source source, Result result) throws TransformerException {
++ this.transformerFactory.newTransformer().transform(source, result);
++ }
++
++
++ private static class CountingOutputStream extends OutputStream {
++
++ private long count = 0;
++
++ @Override
++ public void write(int b) throws IOException {
++ count++;
++ }
++
++ @Override
++ public void write(byte[] b) throws IOException {
++ count += b.length;
++ }
++
++ @Override
++ public void write(byte[] b, int off, int len) throws IOException {
++ count += len;
+ }
+ }
+
+diff --git a/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java b/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java
+index bb20f8a..8d47c22 100644
+--- a/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java
++++ b/projects/org.springframework.web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2002-2010 the original author or authors.
++ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+@@ -16,35 +16,60 @@
+
+ package org.springframework.http.converter.xml;
+
++import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
++import static org.junit.Assert.*;
++import static org.junit.Assert.assertNotEquals;
++
++import java.io.IOException;
++import java.io.InputStream;
+ import java.io.InputStreamReader;
++import java.io.StringReader;
+ import java.nio.charset.Charset;
++
+ import javax.xml.parsers.DocumentBuilderFactory;
++import javax.xml.stream.XMLStreamException;
++import javax.xml.stream.XMLStreamReader;
+ import javax.xml.transform.Source;
+ import javax.xml.transform.dom.DOMSource;
+ import javax.xml.transform.sax.SAXSource;
++import javax.xml.transform.stax.StAXSource;
+ import javax.xml.transform.stream.StreamSource;
+
+-import static org.custommonkey.xmlunit.XMLAssert.*;
+ import org.junit.Before;
+ import org.junit.Test;
+-import org.w3c.dom.Document;
+-import org.w3c.dom.Element;
+-import org.xml.sax.InputSource;
+
++import org.springframework.core.io.ClassPathResource;
++import org.springframework.core.io.Resource;
+ import org.springframework.http.MediaType;
+ import org.springframework.http.MockHttpInputMessage;
+ import org.springframework.http.MockHttpOutputMessage;
+ import org.springframework.util.FileCopyUtils;
++import org.w3c.dom.Document;
++import org.w3c.dom.Element;
++import org.xml.sax.InputSource;
++import org.xml.sax.SAXException;
++import org.xml.sax.XMLReader;
++import org.xml.sax.helpers.DefaultHandler;
+
+-/** @author Arjen Poutsma */
+- at SuppressWarnings("unchecked")
++/**
++ * @author Arjen Poutsma
++ */
+ public class SourceHttpMessageConverterTests {
+
++ private static final String BODY = "<root>Hello World</root>";
++
+ private SourceHttpMessageConverter<Source> converter;
+
++ private String bodyExternal;
++
+ @Before
+- public void setUp() {
++ public void setUp() throws IOException {
+ converter = new SourceHttpMessageConverter<Source>();
++ Resource external = new ClassPathResource("external.txt", getClass());
++
++ bodyExternal = "<!DOCTYPE root [" +
++ " <!ELEMENT root ANY >\n" +
++ " <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]><root>&ext;</root>";
+ }
+
+ @Test
+@@ -62,45 +87,100 @@ public class SourceHttpMessageConverterTests {
+
+ @Test
+ public void readDOMSource() throws Exception {
+- String body = "<root>Hello World</root>";
+- MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(BODY.getBytes("UTF-8"));
++ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
++ DOMSource result = (DOMSource) converter.read(DOMSource.class, inputMessage);
++ Document document = (Document) result.getNode();
++ assertEquals("Invalid result", "root", document.getDocumentElement().getLocalName());
++ }
++
++ @Test
++ public void readDOMSourceExternal() throws Exception {
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(bodyExternal.getBytes("UTF-8"));
+ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
+ DOMSource result = (DOMSource) converter.read(DOMSource.class, inputMessage);
+ Document document = (Document) result.getNode();
+ assertEquals("Invalid result", "root", document.getDocumentElement().getLocalName());
++ assertNotEquals("Invalid result", "Foo Bar", document.getDocumentElement().getTextContent());
+ }
+
+ @Test
+ public void readSAXSource() throws Exception {
+- String body = "<root>Hello World</root>";
+- MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(BODY.getBytes("UTF-8"));
+ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
+ SAXSource result = (SAXSource) converter.read(SAXSource.class, inputMessage);
+ InputSource inputSource = result.getInputSource();
+ String s = FileCopyUtils.copyToString(new InputStreamReader(inputSource.getByteStream()));
+- assertXMLEqual("Invalid result", body, s);
++ assertXMLEqual("Invalid result", BODY, s);
+ }
+
+ @Test
++ public void readSAXSourceExternal() throws Exception {
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(bodyExternal.getBytes("UTF-8"));
++ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
++ SAXSource result = (SAXSource) converter.read(SAXSource.class, inputMessage);
++ InputSource inputSource = result.getInputSource();
++ XMLReader reader = result.getXMLReader();
++ reader.setContentHandler(new DefaultHandler() {
++ @Override
++ public void characters(char[] ch, int start, int length) throws SAXException {
++ String s = new String(ch, start, length);
++ assertNotEquals("Invalid result", "Foo Bar", s);
++ }
++ });
++ reader.parse(inputSource);
++ }
++
++ @Test
++ public void readStAXSource() throws Exception {
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(BODY.getBytes("UTF-8"));
++ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
++ StAXSource result = (StAXSource) converter.read(StAXSource.class, inputMessage);
++ XMLStreamReader streamReader = result.getXMLStreamReader();
++ assertTrue(streamReader.hasNext());
++ streamReader.nextTag();
++ String s = streamReader.getLocalName();
++ assertEquals("root", s);
++ s = streamReader.getElementText();
++ assertEquals("Hello World", s);
++ streamReader.close();
++ }
++
++ @Test
++ public void readStAXSourceExternal() throws Exception {
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(bodyExternal.getBytes("UTF-8"));
++ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
++ StAXSource result = (StAXSource) converter.read(StAXSource.class, inputMessage);
++ XMLStreamReader streamReader = result.getXMLStreamReader();
++ assertTrue(streamReader.hasNext());
++ streamReader.next();
++ streamReader.next();
++ String s = streamReader.getLocalName();
++ assertEquals("root", s);
++ s = streamReader.getElementText();
++ assertNotEquals("Foo Bar", s);
++ streamReader.close();
++ }
++
++
++ @Test
+ public void readStreamSource() throws Exception {
+- String body = "<root>Hello World</root>";
+- MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(BODY.getBytes("UTF-8"));
+ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
+ StreamSource result = (StreamSource) converter.read(StreamSource.class, inputMessage);
+ String s = FileCopyUtils.copyToString(new InputStreamReader(result.getInputStream()));
+- assertXMLEqual("Invalid result", body, s);
++ assertXMLEqual("Invalid result", BODY, s);
+ }
+
+ @Test
+ public void readSource() throws Exception {
+- String body = "<root>Hello World</root>";
+- MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
++ MockHttpInputMessage inputMessage = new MockHttpInputMessage(BODY.getBytes("UTF-8"));
+ inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
+ converter.read(Source.class, inputMessage);
+ }
+
+ @Test
+- public void write() throws Exception {
++ public void writeDOMSource() throws Exception {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ Document document = documentBuilderFactory.newDocumentBuilder().newDocument();
+@@ -115,7 +195,34 @@ public class SourceHttpMessageConverterTests {
+ outputMessage.getBodyAsString(Charset.forName("UTF-8")));
+ assertEquals("Invalid content-type", new MediaType("application", "xml"),
+ outputMessage.getHeaders().getContentType());
++ assertEquals("Invalid content-length", outputMessage.getBodyAsBytes().length,
++ outputMessage.getHeaders().getContentLength());
+ }
+
++ @Test
++ public void writeSAXSource() throws Exception {
++ String xml = "<root>Hello World</root>";
++ SAXSource saxSource = new SAXSource(new InputSource(new StringReader(xml)));
++
++ MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
++ converter.write(saxSource, null, outputMessage);
++ assertXMLEqual("Invalid result", "<root>Hello World</root>",
++ outputMessage.getBodyAsString(Charset.forName("UTF-8")));
++ assertEquals("Invalid content-type", new MediaType("application", "xml"),
++ outputMessage.getHeaders().getContentType());
++ }
++
++ @Test
++ public void writeStreamSource() throws Exception {
++ String xml = "<root>Hello World</root>";
++ StreamSource streamSource = new StreamSource(new StringReader(xml));
++
++ MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
++ converter.write(streamSource, null, outputMessage);
++ assertXMLEqual("Invalid result", "<root>Hello World</root>",
++ outputMessage.getBodyAsString(Charset.forName("UTF-8")));
++ assertEquals("Invalid content-type", new MediaType("application", "xml"),
++ outputMessage.getHeaders().getContentType());
++ }
+
+ }
+diff --git a/projects/org.springframework.web/src/test/resources/org/springframework/http/converter/xml/external.txt b/projects/org.springframework.web/src/test/resources/org/springframework/http/converter/xml/external.txt
+new file mode 100644
+index 0000000..76c7ac2
+--- /dev/null
++++ b/projects/org.springframework.web/src/test/resources/org/springframework/http/converter/xml/external.txt
+@@ -0,0 +1 @@
++Foo Bar
diff --git a/debian/patches/CVE-2013-6430.patch b/debian/patches/CVE-2013-6430.patch
new file mode 100644
index 0000000..7c4c362
--- /dev/null
+++ b/debian/patches/CVE-2013-6430.patch
@@ -0,0 +1,151 @@
+From: Markus Koschany <apo at gambaru.de>
+Date: Thu, 23 Jan 2014 00:03:13 +0100
+Subject: CVE-2013-6430
+
+Bug: http://bugs.debian.org/735420
+---
+ .../springframework/web/util/JavaScriptUtils.java | 35 ++++++++---
+ .../web/util/JavaScriptUtilsTests.java | 67 ++++++++++++++++++++++
+ 2 files changed, 95 insertions(+), 7 deletions(-)
+ create mode 100644 projects/org.springframework.web/src/test/java/org/springframework/web/util/JavaScriptUtilsTests.java
+
+diff --git a/projects/org.springframework.web/src/main/java/org/springframework/web/util/JavaScriptUtils.java b/projects/org.springframework.web/src/main/java/org/springframework/web/util/JavaScriptUtils.java
+index b28d398..861b46f 100644
+--- a/projects/org.springframework.web/src/main/java/org/springframework/web/util/JavaScriptUtils.java
++++ b/projects/org.springframework.web/src/main/java/org/springframework/web/util/JavaScriptUtils.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2002-2008 the original author or authors.
++ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+@@ -21,21 +21,21 @@ package org.springframework.web.util;
+ * Escapes based on the JavaScript 1.5 recommendation.
+ *
+ * <p>Reference:
+- * <a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Literals#String_Literals">
+- * Core JavaScript 1.5 Guide
+- * </a>
++ * <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Values,_variables,_and_literals#String_literals">
++ * JavaScript Guide</a> on Mozilla Developer Network.
+ *
+ * @author Juergen Hoeller
+ * @author Rob Harrop
++ * @author Rossen Stoyanchev
+ * @since 1.1.1
+ */
+ public class JavaScriptUtils {
+
+ /**
+- * Turn special characters into escaped characters conforming to JavaScript.
+- * Handles complete character set defined in HTML 4.01 recommendation.
++ * Turn JavaScript special characters into escaped characters.
++ *
+ * @param input the input string
+- * @return the escaped string
++ * @return the string with escaped characters
+ */
+ public static String javaScriptEscape(String input) {
+ if (input == null) {
+@@ -73,6 +73,27 @@ public class JavaScriptUtils {
+ else if (c == '\f') {
+ filtered.append("\\f");
+ }
++ else if (c == '\b') {
++ filtered.append("\\b");
++ }
++ // No '\v' in Java, use octal value for VT ascii char
++ else if (c == '\013') {
++ filtered.append("\\v");
++ }
++ else if (c == '<') {
++ filtered.append("\\u003C");
++ }
++ else if (c == '>') {
++ filtered.append("\\u003E");
++ }
++ // Unicode for PS (line terminator in ECMA-262)
++ else if (c == '\u2028') {
++ filtered.append("\\u2028");
++ }
++ // Unicode for LS (line terminator in ECMA-262)
++ else if (c == '\u2029') {
++ filtered.append("\\u2029");
++ }
+ else {
+ filtered.append(c);
+ }
+diff --git a/projects/org.springframework.web/src/test/java/org/springframework/web/util/JavaScriptUtilsTests.java b/projects/org.springframework.web/src/test/java/org/springframework/web/util/JavaScriptUtilsTests.java
+new file mode 100644
+index 0000000..182f18e
+--- /dev/null
++++ b/projects/org.springframework.web/src/test/java/org/springframework/web/util/JavaScriptUtilsTests.java
+@@ -0,0 +1,67 @@
++/*
++ * Copyright 2004-2013 the original author or authors.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package org.springframework.web.util;
++
++import static org.junit.Assert.*;
++
++import java.io.UnsupportedEncodingException;
++
++import org.junit.Test;
++
++/**
++ * Test fixture for {@link JavaScriptUtils}.
++ *
++ * @author Rossen Stoyanchev
++ */
++public class JavaScriptUtilsTests {
++
++ @Test
++ public void escape() {
++ StringBuilder sb = new StringBuilder();
++ sb.append('"');
++ sb.append("'");
++ sb.append("\\");
++ sb.append("/");
++ sb.append("\t");
++ sb.append("\n");
++ sb.append("\r");
++ sb.append("\f");
++ sb.append("\b");
++ sb.append("\013");
++ assertEquals("\\\"\\'\\\\\\/\\t\\n\\n\\f\\b\\v", JavaScriptUtils.javaScriptEscape(sb.toString()));
++ }
++
++ // SPR-9983
++
++ @Test
++ public void escapePsLsLineTerminators() {
++ StringBuilder sb = new StringBuilder();
++ sb.append('\u2028');
++ sb.append('\u2029');
++ String result = JavaScriptUtils.javaScriptEscape(sb.toString());
++
++ assertEquals("\\u2028\\u2029", result);
++ }
++
++ // SPR-9983
++
++ @Test
++ public void escapeLessThanGreaterThanSigns() throws UnsupportedEncodingException {
++ assertEquals("\\u003C\\u003E", JavaScriptUtils.javaScriptEscape("<>"));
++ }
++
++}
diff --git a/debian/patches/series b/debian/patches/series
index ca5006b..838e243 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -8,3 +8,5 @@
0009_hibernate_validator_41.diff
0010_velocity_17.diff
Add-processExternalEntities-to-JAXB2Marshaller.patch
+CVE-2013-6429.patch
+CVE-2013-6430.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libspring-java.git
More information about the pkg-java-commits
mailing list