Clearing the buffer in case of parser errors that lead to a

connection failure.
This commit is contained in:
Simone Bordet 2014-12-18 15:01:34 +01:00
parent 1c2c83e962
commit 7f98b64658
12 changed files with 49 additions and 5 deletions

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.http2.frames.PushPromiseFrame;
import org.eclipse.jetty.http2.frames.ResetFrame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -49,8 +50,9 @@ public abstract class BodyParser
public abstract Result parse(ByteBuffer buffer);
protected boolean emptyBody()
protected boolean emptyBody(ByteBuffer buffer)
{
BufferUtil.clear(buffer);
notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_frame");
return false;
}

View File

@ -45,10 +45,11 @@ public class DataBodyParser extends BodyParser
}
@Override
protected boolean emptyBody()
protected boolean emptyBody(ByteBuffer buffer)
{
if (isPadding())
{
BufferUtil.clear(buffer);
notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_data_frame");
return false;
}
@ -68,6 +69,7 @@ public class DataBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() == 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_data_frame");
}
length = getBodyLength();
@ -91,6 +93,7 @@ public class DataBodyParser extends BodyParser
loop = length == 0;
if (length < 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_data_frame_padding");
}
break;

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.frames.GoAwayFrame;
import org.eclipse.jetty.util.BufferUtil;
public class GoAwayBodyParser extends BodyParser
{
@ -70,6 +71,7 @@ public class GoAwayBodyParser extends BodyParser
length -= 4;
if (length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_go_away_frame");
}
}
@ -88,6 +90,7 @@ public class GoAwayBodyParser extends BodyParser
--length;
if (cursor > 0 && length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_go_away_frame");
}
if (cursor == 0)
@ -96,6 +99,7 @@ public class GoAwayBodyParser extends BodyParser
state = State.ERROR;
if (length == 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_go_away_frame");
}
}
@ -110,6 +114,7 @@ public class GoAwayBodyParser extends BodyParser
length -= 4;
if (length < 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_go_away_frame");
}
if (length == 0)
@ -132,6 +137,7 @@ public class GoAwayBodyParser extends BodyParser
--length;
if (cursor > 0 && length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_go_away_frame");
}
if (cursor == 0)

View File

@ -56,7 +56,7 @@ public class HeadersBodyParser extends BodyParser
}
@Override
protected boolean emptyBody()
protected boolean emptyBody(ByteBuffer buffer)
{
MetaData metaData = headerBlockParser.parse(BufferUtil.EMPTY_BUFFER, 0);
boolean result = onHeaders(0, 0, false, metaData);
@ -77,12 +77,14 @@ public class HeadersBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() == 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_headers_frame");
}
// For now we don't support HEADERS frames that don't have END_HEADERS.
if (!hasFlag(Flags.END_HEADERS))
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.INTERNAL_ERROR, "unsupported_headers_frame");
}
@ -111,6 +113,7 @@ public class HeadersBodyParser extends BodyParser
loop = length == 0;
if (length < 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_headers_frame_padding");
}
break;
@ -134,6 +137,7 @@ public class HeadersBodyParser extends BodyParser
state = State.WEIGHT;
if (length < 1)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_headers_frame");
}
}
@ -152,6 +156,7 @@ public class HeadersBodyParser extends BodyParser
--length;
if (cursor > 0 && length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_headers_frame");
}
if (cursor == 0)
@ -160,6 +165,7 @@ public class HeadersBodyParser extends BodyParser
state = State.WEIGHT;
if (length < 1)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_headers_frame");
}
}
@ -178,6 +184,7 @@ public class HeadersBodyParser extends BodyParser
MetaData metaData = headerBlockParser.parse(buffer, length);
if (metaData != null)
{
// TODO: optimize of paddingLength==0: reset() here.
state = State.PADDING;
loop = paddingLength == 0;
if (onHeaders(streamId, weight, exclusive, metaData))

View File

@ -33,6 +33,7 @@ import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.http2.hpack.HpackDecoder;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -94,12 +95,13 @@ public class Parser
if (type < 0 || type >= bodyParsers.length)
{
notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "unknown_frame_type_" + type);
BufferUtil.clear(buffer);
return false;
}
BodyParser bodyParser = bodyParsers[type];
if (headerParser.getLength() == 0)
{
boolean async = bodyParser.emptyBody();
boolean async = bodyParser.emptyBody(buffer);
reset();
if (async)
return true;
@ -151,6 +153,7 @@ public class Parser
if (LOG.isDebugEnabled())
LOG.debug(x);
notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "parser_error");
BufferUtil.clear(buffer);
return false;
}
}

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.Flags;
import org.eclipse.jetty.http2.frames.PingFrame;
import org.eclipse.jetty.util.BufferUtil;
public class PingBodyParser extends BodyParser
{
@ -54,11 +55,13 @@ public class PingBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() != 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_ping_frame");
}
// SPEC: wrong body length is treated as connection error.
if (getBodyLength() != 8)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_ping_frame");
}
state = State.PAYLOAD;

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.frames.PrefaceFrame;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -45,6 +46,7 @@ public class PrefaceParser
if (currByte != PrefaceFrame.PREFACE_BYTES[cursor])
{
notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_preface");
BufferUtil.clear(buffer);
return false;
}
++cursor;

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.frames.PriorityFrame;
import org.eclipse.jetty.util.BufferUtil;
public class PriorityBodyParser extends BodyParser
{
@ -55,11 +56,13 @@ public class PriorityBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() == 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_priority_frame");
}
int length = getBodyLength();
if (length != 5)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_priority_frame");
}
state = State.EXCLUSIVE;

View File

@ -24,6 +24,7 @@ import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.Flags;
import org.eclipse.jetty.http2.frames.PushPromiseFrame;
import org.eclipse.jetty.util.BufferUtil;
public class PushPromiseBodyParser extends BodyParser
{
@ -62,12 +63,14 @@ public class PushPromiseBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() == 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_push_promise_frame");
}
// For now we don't support PUSH_PROMISE frames that don't have END_HEADERS.
if (!hasFlag(Flags.END_HEADERS))
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.INTERNAL_ERROR, "unsupported_push_promise_frame");
}
@ -91,6 +94,7 @@ public class PushPromiseBodyParser extends BodyParser
state = State.STREAM_ID;
if (length < 4)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_push_promise_frame");
}
break;
@ -120,6 +124,7 @@ public class PushPromiseBodyParser extends BodyParser
--length;
if (cursor > 0 && length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_push_promise_frame");
}
if (cursor == 0)

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.frames.ResetFrame;
import org.eclipse.jetty.util.BufferUtil;
public class ResetBodyParser extends BodyParser
{
@ -53,11 +54,13 @@ public class ResetBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() == 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_rst_stream_frame");
}
int length = getBodyLength();
if (length != 4)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_rst_stream_frame");
}
state = State.ERROR;

View File

@ -25,6 +25,7 @@ import java.util.Map;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.Flags;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -54,7 +55,7 @@ public class SettingsBodyParser extends BodyParser
}
@Override
protected boolean emptyBody()
protected boolean emptyBody(ByteBuffer buffer)
{
return onSettings(new HashMap<Integer, Integer>()) == Result.ASYNC;
}
@ -71,6 +72,7 @@ public class SettingsBodyParser extends BodyParser
// SPEC: wrong streamId is treated as connection error.
if (getStreamId() != 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.PROTOCOL_ERROR, "invalid_settings_frame");
}
length = getBodyLength();
@ -87,6 +89,7 @@ public class SettingsBodyParser extends BodyParser
length -= 2;
if (length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_settings_frame");
}
}
@ -106,6 +109,7 @@ public class SettingsBodyParser extends BodyParser
--length;
if (length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_settings_frame");
}
if (cursor == 0)
@ -145,6 +149,7 @@ public class SettingsBodyParser extends BodyParser
--length;
if (cursor > 0 && length <= 0)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_settings_frame");
}
if (cursor == 0)

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCodes;
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.BufferUtil;
public class WindowUpdateBodyParser extends BodyParser
{
@ -53,6 +54,7 @@ public class WindowUpdateBodyParser extends BodyParser
int length = getBodyLength();
if (length != 4)
{
BufferUtil.clear(buffer);
return notifyConnectionFailure(ErrorCodes.FRAME_SIZE_ERROR, "invalid_window_update_frame");
}
state = State.WINDOW_DELTA;