[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