[#1293] Fix IllegalBufferAccessException in HttpPostRequestDecoder
* Also let HttpPostRequestDecoder extends Iterator and let its Exceptiosn extend DecoderException
This commit is contained in:
parent
a170f05b4b
commit
97bdabad9c
@ -15,7 +15,9 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import io.netty.buffer.BufUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.http.HttpConstants;
|
||||
import io.netty.handler.codec.http.HttpContent;
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
@ -32,6 +34,7 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
@ -41,7 +44,7 @@ import static io.netty.buffer.Unpooled.*;
|
||||
/**
|
||||
* This decoder will decode Body and can handle POST BODY.
|
||||
*/
|
||||
public class HttpPostRequestDecoder {
|
||||
public class HttpPostRequestDecoder implements Iterator<InterfaceHttpData> {
|
||||
/**
|
||||
* Factory used to create InterfaceHttpData
|
||||
*/
|
||||
@ -347,8 +350,11 @@ public class HttpPostRequestDecoder {
|
||||
* if there is a problem with the charset decoding or other
|
||||
* errors
|
||||
*/
|
||||
public void offer(HttpContent content) throws ErrorDataDecoderException {
|
||||
ByteBuf chunked = content.content();
|
||||
public HttpPostRequestDecoder offer(HttpContent content) throws ErrorDataDecoderException {
|
||||
// Maybe we should better not copy here for performance reasons but this will need
|
||||
// more care by teh caller to release the content in a correct manner later
|
||||
// So maybe something to optimize on a later stage
|
||||
ByteBuf chunked = content.content().copy();
|
||||
if (undecodedChunk == null) {
|
||||
undecodedChunk = chunked;
|
||||
} else {
|
||||
@ -361,6 +367,7 @@ public class HttpPostRequestDecoder {
|
||||
isLastChunk = true;
|
||||
}
|
||||
parseBody();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -483,7 +490,7 @@ public class HttpPostRequestDecoder {
|
||||
if (read == '&') {
|
||||
currentStatus = MultiPartStatus.DISPOSITION;
|
||||
ampersandpos = currentpos - 1;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
firstpos = currentpos;
|
||||
contRead = true;
|
||||
} else if (read == HttpConstants.CR) {
|
||||
@ -493,7 +500,7 @@ public class HttpPostRequestDecoder {
|
||||
if (read == HttpConstants.LF) {
|
||||
currentStatus = MultiPartStatus.PREEPILOGUE;
|
||||
ampersandpos = currentpos - 2;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
firstpos = currentpos;
|
||||
contRead = false;
|
||||
} else {
|
||||
@ -506,7 +513,7 @@ public class HttpPostRequestDecoder {
|
||||
} else if (read == HttpConstants.LF) {
|
||||
currentStatus = MultiPartStatus.PREEPILOGUE;
|
||||
ampersandpos = currentpos - 1;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
firstpos = currentpos;
|
||||
contRead = false;
|
||||
}
|
||||
@ -520,7 +527,7 @@ public class HttpPostRequestDecoder {
|
||||
// special case
|
||||
ampersandpos = currentpos;
|
||||
if (ampersandpos > firstpos) {
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
} else if (!currentAttribute.isCompleted()) {
|
||||
setFinalBuffer(EMPTY_BUFFER);
|
||||
}
|
||||
@ -531,7 +538,7 @@ public class HttpPostRequestDecoder {
|
||||
if (contRead && currentAttribute != null) {
|
||||
// reset index except if to continue in case of FIELD getStatus
|
||||
if (currentStatus == MultiPartStatus.FIELD) {
|
||||
currentAttribute.addContent(undecodedChunk.slice(firstpos, currentpos - firstpos), false);
|
||||
currentAttribute.addContent(undecodedChunk.slice(firstpos, currentpos - firstpos).retain(), false);
|
||||
firstpos = currentpos;
|
||||
}
|
||||
undecodedChunk.readerIndex(firstpos);
|
||||
@ -603,7 +610,7 @@ public class HttpPostRequestDecoder {
|
||||
if (read == '&') {
|
||||
currentStatus = MultiPartStatus.DISPOSITION;
|
||||
ampersandpos = currentpos - 1;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
firstpos = currentpos;
|
||||
contRead = true;
|
||||
} else if (read == HttpConstants.CR) {
|
||||
@ -614,7 +621,7 @@ public class HttpPostRequestDecoder {
|
||||
currentStatus = MultiPartStatus.PREEPILOGUE;
|
||||
ampersandpos = currentpos - 2;
|
||||
sao.setReadPosition(0);
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
firstpos = currentpos;
|
||||
contRead = false;
|
||||
break loop;
|
||||
@ -632,7 +639,7 @@ public class HttpPostRequestDecoder {
|
||||
currentStatus = MultiPartStatus.PREEPILOGUE;
|
||||
ampersandpos = currentpos - 1;
|
||||
sao.setReadPosition(0);
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
firstpos = currentpos;
|
||||
contRead = false;
|
||||
break loop;
|
||||
@ -649,7 +656,7 @@ public class HttpPostRequestDecoder {
|
||||
// special case
|
||||
ampersandpos = currentpos;
|
||||
if (ampersandpos > firstpos) {
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos).retain());
|
||||
} else if (!currentAttribute.isCompleted()) {
|
||||
setFinalBuffer(EMPTY_BUFFER);
|
||||
}
|
||||
@ -660,7 +667,7 @@ public class HttpPostRequestDecoder {
|
||||
if (contRead && currentAttribute != null) {
|
||||
// reset index except if to continue in case of FIELD getStatus
|
||||
if (currentStatus == MultiPartStatus.FIELD) {
|
||||
currentAttribute.addContent(undecodedChunk.slice(firstpos, currentpos - firstpos), false);
|
||||
currentAttribute.addContent(undecodedChunk.slice(firstpos, currentpos - firstpos).retain(), false);
|
||||
firstpos = currentpos;
|
||||
}
|
||||
undecodedChunk.readerIndex(firstpos);
|
||||
@ -1560,7 +1567,7 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
}
|
||||
}
|
||||
ByteBuf buffer = undecodedChunk.slice(readerIndex, lastPosition - readerIndex);
|
||||
ByteBuf buffer = undecodedChunk.slice(readerIndex, lastPosition - readerIndex).retain();
|
||||
if (found) {
|
||||
// found so lastPosition is correct and final
|
||||
try {
|
||||
@ -1678,7 +1685,7 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
}
|
||||
lastPosition = sao.getReadPosition(lastrealpos);
|
||||
ByteBuf buffer = undecodedChunk.slice(readerIndex, lastPosition - readerIndex);
|
||||
ByteBuf buffer = undecodedChunk.slice(readerIndex, lastPosition - readerIndex).retain();
|
||||
if (found) {
|
||||
// found so lastPosition is correct and final
|
||||
try {
|
||||
@ -1776,14 +1783,16 @@ public class HttpPostRequestDecoder {
|
||||
// delimiter or simple one)
|
||||
// so go back of delimiter size
|
||||
try {
|
||||
currentAttribute.addContent(undecodedChunk.slice(readerIndex, lastPosition - readerIndex), true);
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(readerIndex, lastPosition - readerIndex).retain(), true);
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
undecodedChunk.readerIndex(lastPosition);
|
||||
} else {
|
||||
try {
|
||||
currentAttribute.addContent(undecodedChunk.slice(readerIndex, lastPosition - readerIndex), false);
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(readerIndex, lastPosition - readerIndex).retain(), false);
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
@ -1879,14 +1888,16 @@ public class HttpPostRequestDecoder {
|
||||
// delimiter or simple one)
|
||||
// so go back of delimiter size
|
||||
try {
|
||||
currentAttribute.addContent(undecodedChunk.slice(readerIndex, lastPosition - readerIndex), true);
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(readerIndex, lastPosition - readerIndex).retain(), true);
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
undecodedChunk.readerIndex(lastPosition);
|
||||
} else {
|
||||
try {
|
||||
currentAttribute.addContent(undecodedChunk.slice(readerIndex, lastPosition - readerIndex), false);
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(readerIndex, lastPosition - readerIndex).retain(), false);
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
@ -2026,11 +2037,16 @@ public class HttpPostRequestDecoder {
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception when try reading data from request in chunked format, and not
|
||||
* enough data are available (need more chunks)
|
||||
*/
|
||||
public static class NotEnoughDataDecoderException extends Exception {
|
||||
public static class NotEnoughDataDecoderException extends DecoderException {
|
||||
private static final long serialVersionUID = -7846841864603865638L;
|
||||
|
||||
public NotEnoughDataDecoderException() {
|
||||
@ -2052,14 +2068,14 @@ public class HttpPostRequestDecoder {
|
||||
/**
|
||||
* Exception when the body is fully decoded, even if there is still data
|
||||
*/
|
||||
public static class EndOfDataDecoderException extends Exception {
|
||||
public static class EndOfDataDecoderException extends DecoderException {
|
||||
private static final long serialVersionUID = 1336267941020800769L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception when an error occurs while decoding
|
||||
*/
|
||||
public static class ErrorDataDecoderException extends Exception {
|
||||
public static class ErrorDataDecoderException extends DecoderException {
|
||||
private static final long serialVersionUID = 5020247425493164465L;
|
||||
|
||||
public ErrorDataDecoderException() {
|
||||
@ -2081,7 +2097,7 @@ public class HttpPostRequestDecoder {
|
||||
/**
|
||||
* Exception when an unappropriated getMethod was called on a request
|
||||
*/
|
||||
public static class IncompatibleDataDecoderException extends Exception {
|
||||
public static class IncompatibleDataDecoderException extends DecoderException {
|
||||
private static final long serialVersionUID = -953268047926250267L;
|
||||
|
||||
public IncompatibleDataDecoderException() {
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.example.http.upload;
|
||||
|
||||
import io.netty.buffer.BufUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@ -297,6 +298,7 @@ public class HttpUploadServerHandler extends ChannelInboundMessageHandlerAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
//BufUtil.release(data);
|
||||
}
|
||||
|
||||
private void writeResponse(Channel channel) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user