Permalink
Browse files

Fix CVE-2014-0050. Specially crafted input can trigger a DoS if the b…

…uffer used by the <code>MultipartStream</code> is not big enough. When constructing <code>MultipartStream</code> enforce the requirements for buffer size by throwing an <code>IllegalArgumentException</code> if the requested buffer size is too small. This prevents the DoS.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/fileupload/trunk@1565143 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
markt-asf committed Feb 6, 2014
1 parent 401ba23 commit c61ff05b3241cb14d989b67209e57aa71540417a
@@ -51,6 +51,13 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="markt" type="fix">
Correct example in usage documentation so it compiles.
</action>
<action dev="markt" type="fix">
Fix CVE-2014-0050. Specially crafted input can trigger a DoS if the
buffer used by the <code>MultipartStream</code> is not big enough. When
constructing <code>MultipartStream</code> enforce the requirements for
buffer size by throwing an <code>IllegalArgumentException</code> if the
requested buffer size is too small. This prevents the DoS.
</action>
</release>
<release version="1.3" description="maintenance release, JDK1.5 update" date="2013-03-27">
@@ -991,7 +991,12 @@ protected void raiseError(long pSizeMax, long pCount)
}
notifier = new MultipartStream.ProgressNotifier(listener, requestSize);
multi = new MultipartStream(input, boundary, notifier);
try {
multi = new MultipartStream(input, boundary, notifier);
} catch (IllegalArgumentException iae) {
throw new InvalidContentTypeException(
format("The boundary specified in the %s header is too long", CONTENT_TYPE), iae);
}
multi.setHeaderEncoding(charEncoding);
skipPreamble = true;
@@ -1183,7 +1188,7 @@ public Throwable getCause() {
* detail message.
*/
public InvalidContentTypeException() {
// Nothing to do.
super();
}
/**
@@ -1196,6 +1201,9 @@ public InvalidContentTypeException(String message) {
super(message);
}
public InvalidContentTypeException(String msg, Throwable cause) {
super(msg, cause);
}
}
/**
@@ -268,10 +268,8 @@ private void notifyListener() {
/**
* Creates a new instance.
*
* @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[],
* org.apache.commons.fileupload.MultipartStream.ProgressNotifier)},
* or {@link #MultipartStream(InputStream, byte[], int,
* org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}
* @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[], int,
* ProgressNotifier)}
*/
@Deprecated
public MultipartStream() {
@@ -292,10 +290,8 @@ public MultipartStream() {
* <code>encapsulations</code>.
* @param bufSize The size of the buffer to be used, in bytes.
*
* @see #MultipartStream(InputStream, byte[],
* MultipartStream.ProgressNotifier)
* @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[], int,
* org.apache.commons.fileupload.MultipartStream.ProgressNotifier)}.
* ProgressNotifier)}.
*/
@Deprecated
public MultipartStream(InputStream input, byte[] boundary, int bufSize) {
@@ -317,8 +313,7 @@ public MultipartStream(InputStream input, byte[] boundary, int bufSize) {
* @param pNotifier The notifier, which is used for calling the
* progress listener, if any.
*
* @see #MultipartStream(InputStream, byte[],
* MultipartStream.ProgressNotifier)
* @throws IllegalArgumentException If the buffer size is too small
*/
public MultipartStream(InputStream input,
byte[] boundary,
@@ -331,9 +326,14 @@ public MultipartStream(InputStream input,
// We prepend CR/LF to the boundary to chop trailing CR/LF from
// body-data tokens.
this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length];
this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;
if (bufSize < this.boundaryLength + 1) {
throw new IllegalArgumentException(
"The buffer size specified for the MultipartStream is too small");
}
this.boundary = new byte[this.boundaryLength];
this.keepRegion = this.boundary.length;
System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0,
BOUNDARY_PREFIX.length);
System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length,
@@ -352,8 +352,7 @@ public MultipartStream(InputStream input,
* @param pNotifier An object for calling the progress listener, if any.
*
*
* @see #MultipartStream(InputStream, byte[], int,
* MultipartStream.ProgressNotifier)
* @see #MultipartStream(InputStream, byte[], int, ProgressNotifier)
*/
MultipartStream(InputStream input,
byte[] boundary,
@@ -368,10 +367,8 @@ public MultipartStream(InputStream input,
* @param boundary The token used for dividing the stream into
* <code>encapsulations</code>.
*
* @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[],
* MultipartStream.ProgressNotifier)}.
* @see #MultipartStream(InputStream, byte[], int,
* MultipartStream.ProgressNotifier)
* @deprecated 1.2.1 Use {@link #MultipartStream(InputStream, byte[], int,
* ProgressNotifier)}.
*/
@Deprecated
public MultipartStream(InputStream input,
@@ -38,7 +38,8 @@ public void testThreeParamConstructor() throws Exception {
final byte[] contents = strData.getBytes();
InputStream input = new ByteArrayInputStream(contents);
byte[] boundary = BOUNDARY_TEXT.getBytes();
int iBufSize = boundary.length;
int iBufSize =
boundary.length + MultipartStream.BOUNDARY_PREFIX.length + 1;
MultipartStream ms = new MultipartStream(
input,
boundary,
@@ -47,6 +48,21 @@ public void testThreeParamConstructor() throws Exception {
assertNotNull(ms);
}
@Test(expected=IllegalArgumentException.class)
public void testSmallBuffer() throws Exception {
final String strData = "foobar";
final byte[] contents = strData.getBytes();
InputStream input = new ByteArrayInputStream(contents);
byte[] boundary = BOUNDARY_TEXT.getBytes();
int iBufSize = 1;
@SuppressWarnings("unused")
MultipartStream ms = new MultipartStream(
input,
boundary,
iBufSize,
new MultipartStream.ProgressNotifier(null, contents.length));
}
@Test
public void testTwoParamConstructor() throws Exception {
final String strData = "foobar";

0 comments on commit c61ff05

Please sign in to comment.