Ensure entire request body is consumed before handling fin
This completes the fix for #704
This commit is contained in:
parent
21de2aee13
commit
50f187aa3e
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue