Merge remote-tracking branch 'origin/jetty-9.3.x' into jetty-9.4.x

This commit is contained in:
Greg Wilkins 2016-12-02 13:01:26 +11:00
commit 3ea2d1cf95
4 changed files with 88 additions and 12 deletions

View File

@ -116,7 +116,7 @@ public class HpackContext
private static final Trie<StaticEntry> __staticNameMap = new ArrayTernaryTrie<>(true,512);
private static final StaticEntry[] __staticTableByHeader = new StaticEntry[HttpHeader.UNKNOWN.ordinal()];
private static final StaticEntry[] __staticTable=new StaticEntry[STATIC_TABLE.length];
private static final int STATIC_SIZE = STATIC_TABLE.length-1;
public static final int STATIC_SIZE = STATIC_TABLE.length-1;
static
{
Set<String> added = new HashSet<>();

View File

@ -88,7 +88,7 @@ public class HpackEncoder
private int _remoteMaxDynamicTableSize;
private int _localMaxDynamicTableSize;
private int _maxHeaderListSize;
private int _size;
private int _headerListSize;
public HpackEncoder()
{
@ -144,7 +144,7 @@ public class HpackEncoder
if (LOG.isDebugEnabled())
LOG.debug(String.format("CtxTbl[%x] encoding",_context.hashCode()));
_size=0;
_headerListSize=0;
int pos = buffer.position();
// Check the dynamic table sizes!
@ -179,9 +179,9 @@ public class HpackEncoder
encode(buffer,field);
// Check size
if (_maxHeaderListSize>0 && _size>_maxHeaderListSize)
if (_maxHeaderListSize>0 && _headerListSize>_maxHeaderListSize)
{
LOG.warn("Header list size too large {} > {} for {}",_size,_maxHeaderListSize);
LOG.warn("Header list size too large {} > {} for {}",_headerListSize,_maxHeaderListSize);
if (LOG.isDebugEnabled())
LOG.debug("metadata={}",metadata);
}
@ -205,7 +205,7 @@ public class HpackEncoder
field = new HttpField(field.getHeader(),field.getName(),"");
int field_size = field.getName().length() + field.getValue().length();
_size+=field_size+32;
_headerListSize+=field_size+32;
final int p=_debug?buffer.position():-1;
@ -307,9 +307,9 @@ public class HpackEncoder
(huffman?"HuffV":"LitV")+
(indexed?"Idx":(never_index?"!!Idx":"!Idx"));
}
else if (header==HttpHeader.CONTENT_LENGTH && field.getValue().length()>1)
else if (field_size>=_context.getMaxDynamicTableSize() || header==HttpHeader.CONTENT_LENGTH && field.getValue().length()>2)
{
// Non indexed content length for 2 digits or more
// Non indexed if field too large or a content length for 3 digits or more
indexed=false;
encodeName(buffer,(byte)0x00,4,header.asString(),name);
encodeValue(buffer,true,field.getValue());
@ -332,7 +332,8 @@ public class HpackEncoder
// If we want the field referenced, then we add it to our
// table and reference set.
if (indexed)
_context.add(field);
if (_context.add(field)==null)
throw new IllegalStateException();
}
if (_debug)

View File

@ -20,6 +20,7 @@
package org.eclipse.jetty.http2.hpack;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import java.nio.ByteBuffer;
@ -29,6 +30,7 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
@ -185,6 +187,69 @@ public class HpackEncoderTest
}
@Test
public void testFieldLargerThanTable()
{
HttpFields fields = new HttpFields();
HpackEncoder encoder = new HpackEncoder(128);
ByteBuffer buffer0 = BufferUtil.allocate(4096);
int pos = BufferUtil.flipToFill(buffer0);
encoder.encode(buffer0,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer0,pos);
encoder = new HpackEncoder(128);
fields.add(new HttpField("user-agent","jetty/test"));
ByteBuffer buffer1 = BufferUtil.allocate(4096);
pos = BufferUtil.flipToFill(buffer1);
encoder.encode(buffer1,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer1,pos);
encoder = new HpackEncoder(128);
fields.add(new HttpField(":path",
"This is a very large field, whose size is larger than the dynamic table so it should not be indexed as it will not fit in the table ever!"+
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "+
"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY "+
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ "));
ByteBuffer buffer2 = BufferUtil.allocate(4096);
pos = BufferUtil.flipToFill(buffer2);
encoder.encode(buffer2,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer2,pos);
encoder = new HpackEncoder(128);
fields.add(new HttpField("host","somehost"));
ByteBuffer buffer = BufferUtil.allocate(4096);
pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,pos);
//System.err.println(BufferUtil.toHexString(buffer0));
//System.err.println(BufferUtil.toHexString(buffer1));
//System.err.println(BufferUtil.toHexString(buffer2));
//System.err.println(BufferUtil.toHexString(buffer));
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// check first field is static index name and dynamic index body
assertThat((buffer.get(buffer0.remaining())&0xFF)>>6,equalTo(1));
// check first field is static index name and literal body
assertThat((buffer.get(buffer1.remaining())&0xFF)>>4,equalTo(0));
// check first field is static index name and dynamic index body
assertThat((buffer.get(buffer2.remaining())&0xFF)>>6,equalTo(1));
// Only first and third fields are put in the table
HpackContext context = encoder.getHpackContext();
assertThat(context.size(),equalTo(2));
assertThat(context.get(HpackContext.STATIC_SIZE+1).getHttpField().getName(),equalTo("host"));
assertThat(context.get(HpackContext.STATIC_SIZE+2).getHttpField().getName(),equalTo("user-agent"));
assertThat(context.getDynamicTableSize(),equalTo(
context.get(HpackContext.STATIC_SIZE+1).getSize()+context.get(HpackContext.STATIC_SIZE+2).getSize()));
}
}

View File

@ -1126,12 +1126,10 @@ public class BufferUtil
buf.append("\\x").append(TypeUtil.toHexString(b));
}
/* ------------------------------------------------------------ */
/** Convert buffer to a Hex Summary String.
* @param buffer the buffer to generate a hex byte summary from
* @return A string showing the escaped content of the buffer around the
* position and limit (marked with &lt;&lt;&lt; and &gt;&gt;&gt;)
* @return A string showing a summary of the content in hex
*/
public static String toHexSummary(ByteBuffer buffer)
{
@ -1152,6 +1150,18 @@ public class BufferUtil
return buf.toString();
}
/* ------------------------------------------------------------ */
/** Convert buffer to a Hex String.
* @param buffer the buffer to generate a hex byte summary from
* @return A hex string
*/
public static String toHexString(ByteBuffer buffer)
{
if (buffer == null)
return "null";
return TypeUtil.toHexString(toArray(buffer));
}
private final static int[] decDivisors =
{1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};