Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2014-06-18 09:11:23 +0000
committerGreg Wilkins2014-06-18 09:11:23 +0000
commit30affa57c7e2aed1f26902e13e7f476395aa253d (patch)
tree26eb9d524ee9201d8463ba74a55fdf4258fc7187
parent140e7ed0c56ea0afcabba1e1e142ad76d044220c (diff)
downloadorg.eclipse.jetty.project-30affa57c7e2aed1f26902e13e7f476395aa253d.tar.gz
org.eclipse.jetty.project-30affa57c7e2aed1f26902e13e7f476395aa253d.tar.xz
org.eclipse.jetty.project-30affa57c7e2aed1f26902e13e7f476395aa253d.zip
HpackDecoder implements 413 limit
-rw-r--r--jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java22
-rw-r--r--jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java48
-rw-r--r--jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java4
-rw-r--r--jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java50
4 files changed, 114 insertions, 10 deletions
diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java
index 6771ff3983..4a2ec08720 100644
--- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java
+++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java
@@ -27,6 +27,7 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
+import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
import org.eclipse.jetty.util.TypeUtil;
@@ -43,18 +44,21 @@ public class HpackDecoder
public static final Logger LOG = Log.getLogger(HpackDecoder.class);
private final HpackContext _context;
- private final MetaDataBuilder _builder = new MetaDataBuilder();
+ private final MetaDataBuilder _builder;
private int _localMaxHeaderTableSize;
+ @Deprecated
public HpackDecoder()
{
- this(4096);
+ this(4*1024,8*1024);
+ LOG.warn("USE HpackDecoder constructor with maxHeaderSize!!!");
}
- public HpackDecoder(int localMaxHeaderTableSize)
+ public HpackDecoder(int localMaxHeaderTableSize, int maxHeaderSize)
{
_context=new HpackContext(localMaxHeaderTableSize);
_localMaxHeaderTableSize=localMaxHeaderTableSize;
+ _builder = new MetaDataBuilder(maxHeaderSize);
}
public void setLocalMaxHeaderTableSize(int localMaxHeaderTableSize)
@@ -63,9 +67,15 @@ public class HpackDecoder
}
public MetaData decode(ByteBuffer buffer)
- {
+ {
if (LOG.isDebugEnabled())
- LOG.debug(String.format("CtxTbl[%x] decoding",_context.hashCode()));
+ LOG.debug(String.format("CtxTbl[%x] decoding %d octets",_context.hashCode(),buffer.remaining()));
+
+ // If the buffer is big, don't even think about decoding it
+ if (buffer.remaining()>_builder.getMaxSize())
+ throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header frame size "+buffer.remaining()+">"+_builder.getMaxSize());
+
+
while(buffer.hasRemaining())
{
if (LOG.isDebugEnabled())
@@ -129,6 +139,7 @@ public class HpackDecoder
{
huffmanName = (buffer.get()&0x80)==0x80;
int length = NBitInteger.decode(buffer,7);
+ _builder.checkSize(length,huffmanName);
if (huffmanName)
name=Huffman.decode(buffer,length);
else
@@ -147,6 +158,7 @@ public class HpackDecoder
// decode the value
boolean huffmanValue = (buffer.get()&0x80)==0x80;
int length = NBitInteger.decode(buffer,7);
+ _builder.checkSize(length,huffmanValue);
if (huffmanValue)
value=Huffman.decode(buffer,length);
else
diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java
index a372667d0c..2ff9510b32 100644
--- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java
+++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java
@@ -20,10 +20,12 @@
package org.eclipse.jetty.http2.hpack;
+import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HostPortHttpField;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpScheme;
+import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
@@ -32,16 +34,44 @@ import org.eclipse.jetty.http.MetaData;
/* -------------------------------------------------------- */
public class MetaDataBuilder
{
+ private final int _maxSize;
+ private int _size;
private int _status;
private String _method;
private HttpScheme _scheme;
private HostPortHttpField _authority;
private String _path;
- HttpFields _fields = new HttpFields(10);
+ private HttpFields _fields = new HttpFields(10);
+ MetaDataBuilder(int maxSize)
+ {
+ _maxSize=maxSize;
+ }
+
+ /** Get the maxSize.
+ * @return the maxSize
+ */
+ public int getMaxSize()
+ {
+ return _maxSize;
+ }
+
+ /** Get the size.
+ * @return the current size in bytes
+ */
+ public int getSize()
+ {
+ return _size;
+ }
+
public void emit(HttpField field)
{
+ int field_size = field.getName().length()+field.getValue().length();
+ _size+=field_size;
+ if (_size>_maxSize)
+ throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_size+">"+_maxSize);
+
if (field instanceof StaticValueHttpField)
{
StaticValueHttpField value = (StaticValueHttpField)field;
@@ -65,7 +95,6 @@ public class MetaDataBuilder
}
else
{
-
switch(field.getName())
{
case ":status":
@@ -114,6 +143,21 @@ public class MetaDataBuilder
_scheme=null;
_authority=null;
_path=null;
+ _size=0;
}
}
+
+ /* ------------------------------------------------------------ */
+ /** Check that the max size will not be exceeded.
+ * @param length
+ * @param huffmanName
+ */
+ public void checkSize(int length, boolean huffman)
+ {
+ // Apply a huffman fudge factor
+ if (huffman)
+ length=(length*4)/3;
+ if ((_size+length)>_maxSize)
+ throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+(_size+length)+">"+_maxSize);
+ }
}
diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java
index 7857a1bdbf..9fcb6ac5e9 100644
--- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java
+++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java
@@ -43,7 +43,7 @@ public class HpackDecoderTest
@Test
public void testDecodeD_3()
{
- HpackDecoder decoder = new HpackDecoder();
+ HpackDecoder decoder = new HpackDecoder(4096,8192);
// First request
String encoded="828786440f7777772e6578616d706c652e636f6d";
@@ -93,7 +93,7 @@ public class HpackDecoderTest
@Test
public void testDecodeD_4()
{
- HpackDecoder decoder = new HpackDecoder();
+ HpackDecoder decoder = new HpackDecoder(4096,8192);
// First request
String encoded="828786448ce7cf9bebe89b6fb16fa9b6ff";
diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java
index 7cc665b4fd..5a4b4a13f2 100644
--- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java
+++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java
@@ -19,11 +19,16 @@
package org.eclipse.jetty.http2.hpack;
+import static org.junit.Assert.assertEquals;
+
import java.nio.ByteBuffer;
+import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.http.MetaData;
import org.junit.Assert;
import org.junit.Test;
import org.eclipse.jetty.http.MetaData.Request;
@@ -37,7 +42,7 @@ public class HpackTest
public void encodeDecodeResponseTest()
{
HpackEncoder encoder = new HpackEncoder();
- HpackDecoder decoder = new HpackDecoder();
+ HpackDecoder decoder = new HpackDecoder(4096,8192);
ByteBuffer buffer = BufferUtil.allocate(16*1024);
HttpFields fields0 = new HttpFields();
@@ -80,4 +85,47 @@ public class HpackTest
Assert.assertEquals("custom-key",decoded1.getFields().getField("Custom-Key").getName());
}
+
+
+ @Test
+ public void encodeDecodeTooLargeTest()
+ {
+ HpackEncoder encoder = new HpackEncoder();
+ HpackDecoder decoder = new HpackDecoder(4096,101);
+ ByteBuffer buffer = BufferUtil.allocate(16*1024);
+
+ HttpFields fields0 = new HttpFields();
+ fields0.add("1234567890","1234567890123456789012345678901234567890");
+ fields0.add("Cookie","abcdeffhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR");
+ MetaData original0= new MetaData(HttpVersion.HTTP_2,fields0);
+
+ BufferUtil.clearToFill(buffer);
+ encoder.encode(buffer,original0);
+ BufferUtil.flipToFlush(buffer,0);
+ MetaData decoded0 = (MetaData)decoder.decode(buffer);
+
+ Assert.assertEquals(original0,decoded0);
+
+ HttpFields fields1 = new HttpFields();
+ fields1.add("1234567890","1234567890123456789012345678901234567890");
+ fields1.add("Cookie","abcdeffhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR");
+ fields1.add("x","y");
+ MetaData original1 = new MetaData(HttpVersion.HTTP_2,fields1);
+
+ BufferUtil.clearToFill(buffer);
+ encoder.encode(buffer,original1);
+ BufferUtil.flipToFlush(buffer,0);
+ try
+ {
+ decoder.decode(buffer);
+ Assert.fail();
+ }
+ catch(BadMessageException e)
+ {
+ assertEquals(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,e.getCode());
+ }
+
+ }
+
+
}

Back to the top