Ensure entire request body is consumed before handling fin

This completes the fix for #704
This commit is contained in:
Stephen Halter 2016-04-01 12:38:26 -07:00
parent 21de2aee13
commit 50f187aa3e
2 changed files with 61 additions and 24 deletions

View File

@ -249,29 +249,46 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
while (_mode == Mode.Prefix) while (_mode == Mode.Prefix)
{ {
var fin = input.RemoteIntakeFin;
ParseChunkedPrefix(input); ParseChunkedPrefix(input);
if (_mode != Mode.Prefix) if (_mode != Mode.Prefix)
{ {
break; break;
} }
else if (fin)
{
ThrowChunkedRequestIncomplete();
}
await GetDataAsync(input); await input;
} }
while (_mode == Mode.Extension) while (_mode == Mode.Extension)
{ {
var fin = input.RemoteIntakeFin;
ParseExtension(input); ParseExtension(input);
if (_mode != Mode.Extension) if (_mode != Mode.Extension)
{ {
break; break;
} }
else if (fin)
{
ThrowChunkedRequestIncomplete();
}
await GetDataAsync(input); await input;
} }
while (_mode == Mode.Data) while (_mode == Mode.Data)
{ {
var fin = input.RemoteIntakeFin;
int actual = ReadChunkedData(input, buffer.Array, buffer.Offset, buffer.Count); int actual = ReadChunkedData(input, buffer.Array, buffer.Offset, buffer.Count);
if (actual != 0) if (actual != 0)
{ {
return actual; return actual;
@ -280,39 +297,69 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
break; break;
} }
else if (fin)
{
ThrowChunkedRequestIncomplete();
}
await GetDataAsync(input); await input;
} }
while (_mode == Mode.Suffix) while (_mode == Mode.Suffix)
{ {
var fin = input.RemoteIntakeFin;
ParseChunkedSuffix(input); ParseChunkedSuffix(input);
if (_mode != Mode.Suffix) if (_mode != Mode.Suffix)
{ {
break; break;
} }
else if (fin)
{
ThrowChunkedRequestIncomplete();
}
await GetDataAsync(input); await input;
} }
} }
// Chunks finished, parse trailers // Chunks finished, parse trailers
while (_mode == Mode.Trailer) while (_mode == Mode.Trailer)
{ {
var fin = input.RemoteIntakeFin;
ParseChunkedTrailer(input); ParseChunkedTrailer(input);
if (_mode != Mode.Trailer) if (_mode != Mode.Trailer)
{ {
break; break;
} }
else if (fin)
{
ThrowChunkedRequestIncomplete();
}
await GetDataAsync(input); await input;
} }
if (_mode == Mode.TrailerHeaders) if (_mode == Mode.TrailerHeaders)
{ {
while (!_context.TakeMessageHeaders(input, _requestHeaders)) while (!_context.TakeMessageHeaders(input, _requestHeaders))
{ {
await GetDataAsync(input); if (input.RemoteIntakeFin)
{
if (_context.TakeMessageHeaders(input, _requestHeaders))
{
break;
}
else
{
ThrowChunkedRequestIncomplete();
}
}
await input;
} }
_mode = Mode.Complete; _mode = Mode.Complete;
@ -444,10 +491,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
_mode = Mode.Suffix; _mode = Mode.Suffix;
} }
else if (actual == 0)
{
ThrowIfRequestIncomplete(input);
}
return actual; return actual;
} }
@ -532,19 +575,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
} }
} }
private SocketInput GetDataAsync(SocketInput input) private void ThrowChunkedRequestIncomplete()
{ {
ThrowIfRequestIncomplete(input); ThrowBadRequestException("Chunked request incomplete");
return input;
}
private void ThrowIfRequestIncomplete(SocketInput input)
{
if (input.RemoteIntakeFin)
{
ThrowBadRequestException("Chunked request incomplete");
}
} }
private enum Mode private enum Mode

View File

@ -12,6 +12,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
while (input.IsCompleted) while (input.IsCompleted)
{ {
var fin = input.RemoteIntakeFin;
var begin = input.ConsumingStart(); var begin = input.ConsumingStart();
int actual; int actual;
var end = begin.CopyTo(buffer, offset, count, out actual); var end = begin.CopyTo(buffer, offset, count, out actual);
@ -21,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
return actual; return actual;
} }
if (input.RemoteIntakeFin) else if (fin)
{ {
return 0; return 0;
} }
@ -36,6 +38,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
await input; await input;
var fin = input.RemoteIntakeFin;
var begin = input.ConsumingStart(); var begin = input.ConsumingStart();
int actual; int actual;
var end = begin.CopyTo(buffer, offset, count, out actual); var end = begin.CopyTo(buffer, offset, count, out actual);
@ -45,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
{ {
return actual; return actual;
} }
if (input.RemoteIntakeFin) else if (fin)
{ {
return 0; return 0;
} }