Merge pull request #2323 from eclipse/jetty-9.4.x-2232-HttpParser-cleanup

HttpParser cleanup #2232
This commit is contained in:
Joakim Erdfelt 2018-03-15 07:08:46 -05:00 committed by GitHub
commit 5b8fe10154
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 119 additions and 105 deletions

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN; import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN;
import static org.eclipse.jetty.http.HttpTokens.COLON;
import static org.eclipse.jetty.http.HttpTokens.LINE_FEED; import static org.eclipse.jetty.http.HttpTokens.LINE_FEED;
import static org.eclipse.jetty.http.HttpTokens.SPACE; import static org.eclipse.jetty.http.HttpTokens.SPACE;
import static org.eclipse.jetty.http.HttpTokens.TAB; import static org.eclipse.jetty.http.HttpTokens.TAB;
@ -1074,7 +1075,7 @@ public class HttpParser
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Header Folding"); throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Header Folding");
// header value without name - continuation? // header value without name - continuation?
if (_valueString==null) if (_valueString==null || _valueString.isEmpty())
{ {
_string.setLength(0); _string.setLength(0);
_length=0; _length=0;
@ -1166,10 +1167,6 @@ public class HttpParser
default: default:
{ {
// now handle the ch
if (b<HttpTokens.SPACE)
throw new BadMessageException();
// process previous header // process previous header
if (_state==State.HEADER) if (_state==State.HEADER)
parsedHeader(); parsedHeader();
@ -1266,43 +1263,31 @@ public class HttpParser
break; break;
case IN_NAME: case IN_NAME:
if (b>HttpTokens.SPACE && b!=HttpTokens.COLON) switch(b)
{ {
if (_header!=null) case SPACE:
{ case TAB:
setString(_header.asString()); //Ignore trailing whitespaces ?
_header=null; if (!complianceViolation(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME,null))
_headerString=null;
}
_string.append((char)b);
_length=_string.length();
break;
}
// Fallthrough
case WS_AFTER_NAME:
if (b==HttpTokens.COLON)
{
if (_headerString==null)
{ {
_headerString=takeString(); _headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString); _header=HttpHeader.CACHE.get(_headerString);
}
_length=-1; _length=-1;
setState(FieldState.WS_AFTER_NAME);
break;
}
throw new IllegalCharacterException(_state,b,buffer);
case COLON:
_headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString);
_length=-1;
setState(FieldState.VALUE); setState(FieldState.VALUE);
break; break;
}
if (b==HttpTokens.LINE_FEED) case LINE_FEED:
{
if (_headerString==null)
{
_headerString=takeString(); _headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString); _header=HttpHeader.CACHE.get(_headerString);
}
_string.setLength(0); _string.setLength(0);
_valueString=""; _valueString="";
_length=-1; _length=-1;
@ -1312,57 +1297,70 @@ public class HttpParser
setState(FieldState.FIELD); setState(FieldState.FIELD);
break; break;
} }
}
//Ignore trailing whitespaces
if (b==HttpTokens.SPACE && !complianceViolation(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME,null))
{
setState(FieldState.WS_AFTER_NAME);
break;
}
throw new IllegalCharacterException(_state,b,buffer); throw new IllegalCharacterException(_state,b,buffer);
case VALUE: default:
if (b>HttpTokens.SPACE || b<0) if (b<0)
{ throw new IllegalCharacterException(_state,b,buffer);
_string.append((char)(0xff&b));
_string.append((char)b);
_length=_string.length(); _length=_string.length();
setState(FieldState.IN_VALUE);
break; break;
} }
if (b==HttpTokens.SPACE || b==HttpTokens.TAB)
break; break;
if (b==HttpTokens.LINE_FEED) case WS_AFTER_NAME:
switch(b)
{ {
case SPACE:
case TAB:
break;
case COLON:
setState(FieldState.VALUE);
break;
case LINE_FEED:
if (!complianceViolation(HttpComplianceSection.FIELD_COLON,_headerString))
{
setState(FieldState.FIELD);
break;
}
throw new IllegalCharacterException(_state,b,buffer);
default:
throw new IllegalCharacterException(_state,b,buffer);
}
break;
case VALUE:
switch(b)
{
case LINE_FEED:
_string.setLength(0); _string.setLength(0);
_valueString=""; _valueString="";
_length=-1; _length=-1;
setState(FieldState.FIELD); setState(FieldState.FIELD);
break; break;
}
throw new IllegalCharacterException(_state,b,buffer);
case IN_VALUE: case SPACE:
if (b>=HttpTokens.SPACE || b<0 || b==HttpTokens.TAB) case TAB:
{ break;
if (_valueString!=null)
{ default:
setString(_valueString);
_valueString=null;
_field=null;
}
_string.append((char)(0xff&b)); _string.append((char)(0xff&b));
if (b>HttpTokens.SPACE || b<0)
_length=_string.length(); _length=_string.length();
setState(FieldState.IN_VALUE);
break; break;
} }
break;
if (b==HttpTokens.LINE_FEED) case IN_VALUE:
switch(b)
{ {
case LINE_FEED:
if (_length > 0) if (_length > 0)
{ {
_valueString=takeString(); _valueString=takeString();
@ -1370,9 +1368,18 @@ public class HttpParser
} }
setState(FieldState.FIELD); setState(FieldState.FIELD);
break; break;
}
throw new IllegalCharacterException(_state,b,buffer); case SPACE:
case TAB:
_string.append((char)(0xff&b));
break;
default:
_string.append((char)(0xff&b));
_length=_string.length();
break;
}
break;
default: default:
throw new IllegalStateException(_state.toString()); throw new IllegalStateException(_state.toString());

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.http; package org.eclipse.jetty.http;
import static org.eclipse.jetty.http.HttpComplianceSection.NO_FIELD_FOLDING;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
@ -261,6 +262,8 @@ public class HttpParserTest
"Host: localhost\r\n" + "Host: localhost\r\n" +
"Name: value\r\n" + "Name: value\r\n" +
" extra\r\n" + " extra\r\n" +
"Name2: \r\n" +
"\tvalue2\r\n" +
"\r\n"); "\r\n");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
@ -270,10 +273,12 @@ public class HttpParserTest
Assert.assertThat(_bad, Matchers.nullValue()); Assert.assertThat(_bad, Matchers.nullValue());
Assert.assertEquals("Host", _hdr[0]); Assert.assertEquals("Host", _hdr[0]);
Assert.assertEquals("localhost", _val[0]); Assert.assertEquals("localhost", _val[0]);
Assert.assertEquals(2, _headers);
Assert.assertEquals("Name", _hdr[1]); Assert.assertEquals("Name", _hdr[1]);
Assert.assertEquals("value extra", _val[1]); Assert.assertEquals("value extra", _val[1]);
Assert.assertEquals(1, _headers); Assert.assertEquals("Name2", _hdr[2]);
Assert.assertThat(_complianceViolation, contains(HttpComplianceSection.NO_FIELD_FOLDING)); Assert.assertEquals("value2", _val[2]);
Assert.assertThat(_complianceViolation, contains(NO_FIELD_FOLDING,NO_FIELD_FOLDING));
} }
@Test @Test
@ -399,7 +404,7 @@ public class HttpParserTest
ByteBuffer buffer = BufferUtil.toBuffer( ByteBuffer buffer = BufferUtil.toBuffer(
"HTTP/1.1 204 No Content\r\n" + "HTTP/1.1 204 No Content\r\n" +
"Access-Control-Allow-Headers : Origin\r\n" + "Access-Control-Allow-Headers : Origin\r\n" +
"Other: value\r\n" + "Other\t : value\r\n" +
"\r\n"); "\r\n");
HttpParser.ResponseHandler handler = new Handler(); HttpParser.ResponseHandler handler = new Handler();
@ -422,7 +427,7 @@ public class HttpParserTest
Assert.assertEquals("Other", _hdr[1]); Assert.assertEquals("Other", _hdr[1]);
Assert.assertEquals("value", _val[1]); Assert.assertEquals("value", _val[1]);
Assert.assertThat(_complianceViolation, contains(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME)); Assert.assertThat(_complianceViolation, contains(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME,HttpComplianceSection.NO_WS_AFTER_FIELD_NAME));
} }
@Test @Test
@ -709,7 +714,9 @@ public class HttpParserTest
public void testBadHeaderEncoding() throws Exception public void testBadHeaderEncoding() throws Exception
{ {
ByteBuffer buffer = BufferUtil.toBuffer( ByteBuffer buffer = BufferUtil.toBuffer(
"GET / HTTP/1.0\r\nH\u00e6der0: value0\r\n\n\n"); "GET / HTTP/1.0\r\n"
+ "H\u00e6der0: value0\r\n"
+ "\n\n");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser = new HttpParser(handler); HttpParser parser = new HttpParser(handler);