Bug fix for HttpPostMultipartRequestDecoder part decoding with an invalid charset not reported as an ErrorDataDecoderException

Motivation:

The current HttpPostMultipartRequestDecoder can decode multipart/form-data parts with a Content-Type that specifies a charset. When this charset is invalid the Charset.forName() throws an unchecked UnsupportedCharsetException. This exception is not catched by the decoder. It should actually be rethrown as an ErrorDataDecoderException, because the developer using the API would expect this validation failure to be reported as such.

Modifications:

Add a catch block for UnsupportedCharsetException and rethrow it as an ErrorDataDecoderException.

Result:

UnsupportedCharsetException are now rethrown as ErrorDataDecoderException.
This commit is contained in:
Julien Viet 2016-03-09 21:58:40 +01:00 committed by Norman Maurer
parent 5317c7b648
commit 1257c626d4
2 changed files with 69 additions and 0 deletions

View File

@ -32,6 +32,7 @@ import io.netty.util.internal.StringUtil;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -496,6 +497,8 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
localCharset = Charset.forName(charsetAttribute.getValue());
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
} catch (UnsupportedCharsetException e) {
throw new ErrorDataDecoderException(e);
}
}
Attribute nameAttribute = currentFieldAttributes.get(HttpPostBodyUtil.NAME);
@ -828,6 +831,8 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
localCharset = Charset.forName(charsetAttribute.getValue());
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
} catch (UnsupportedCharsetException e) {
throw new ErrorDataDecoderException(e);
}
}
if (currentFileUpload == null) {

View File

@ -31,6 +31,7 @@ import io.netty.handler.codec.http.LastHttpContent;
import io.netty.util.CharsetUtil;
import org.junit.Test;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Arrays;
import static io.netty.util.ReferenceCountUtil.*;
@ -406,4 +407,67 @@ public class HttpPostRequestDecoderTest {
assertFalse(decoder.getBodyHttpDatas().isEmpty());
decoder.destroy();
}
@Test
public void testMultipartRequestWithFileInvalidCharset() throws Exception {
final String boundary = "dLV9Wyq26L_-JQxk6ferf-RT153LhOO";
final DefaultFullHttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST,
"http://localhost");
req.headers().add(HttpHeaders.Names.CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
// Force to use memory-based data.
final DefaultHttpDataFactory inMemoryFactory = new DefaultHttpDataFactory(false);
final String data = "asdf";
final String filename = "tmp;0.txt";
final String body =
"--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"\r\n" +
"Content-Type: image/gif; charset=ABCD\r\n" +
"\r\n" +
data + "\r\n" +
"--" + boundary + "--\r\n";
req.content().writeBytes(body.getBytes(CharsetUtil.UTF_8));
// Create decoder instance to test.
try {
new HttpPostRequestDecoder(inMemoryFactory, req);
fail("Was expecting an ErrorDataDecoderException");
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
} finally {
req.release();
}
}
@Test
public void testMultipartRequestWithFieldInvalidCharset() throws Exception {
final String boundary = "dLV9Wyq26L_-JQxk6ferf-RT153LhOO";
final DefaultFullHttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST,
"http://localhost");
req.headers().add(HttpHeaders.Names.CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
// Force to use memory-based data.
final DefaultHttpDataFactory inMemoryFactory = new DefaultHttpDataFactory(false);
final String aData = "some data would be here. the data should be long enough that it " +
"will be longer than the original buffer length of 256 bytes in " +
"the HttpPostRequestDecoder in order to trigger the issue. Some more " +
"data just to be on the safe side.";
final String body =
"--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"root\"\r\n" +
"Content-Type: text/plain; charset=ABCD\r\n" +
"\r\n" +
aData +
"\r\n" +
"--" + boundary + "--\r\n";
req.content().writeBytes(body.getBytes(CharsetUtil.UTF_8));
// Create decoder instance to test.
try {
new HttpPostRequestDecoder(inMemoryFactory, req);
fail("Was expecting an ErrorDataDecoderException");
} catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
assertTrue(e.getCause() instanceof UnsupportedCharsetException);
} finally {
req.release();
}
}
}