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

View File

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