Check that MaxRequestBufferSize is greater than or equal to MaxRequestHeadersTotalSize (#1491).

This commit is contained in:
Cesar Blum Silveira 2017-03-21 19:25:56 -07:00 committed by GitHub
parent 6c131ea240
commit 72587baac3
3 changed files with 71 additions and 22 deletions

View File

@ -247,6 +247,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel
throw new InvalidOperationException(
$"Maximum request buffer size ({Options.Limits.MaxRequestBufferSize.Value}) must be greater than or equal to maximum request line size ({Options.Limits.MaxRequestLineSize}).");
}
if (Options.Limits.MaxRequestBufferSize.HasValue &&
Options.Limits.MaxRequestBufferSize < Options.Limits.MaxRequestHeadersTotalSize)
{
throw new InvalidOperationException(
$"Maximum request buffer size ({Options.Limits.MaxRequestBufferSize.Value}) must be greater than or equal to maximum request headers size ({Options.Limits.MaxRequestHeadersTotalSize}).");
}
}
private void StartLocalhost(KestrelEngine engine, ServerAddress parsedAddress)

View File

@ -6,9 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -24,13 +22,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{
private const int _dataLength = 20 * 1024 * 1024;
private static readonly string[] _requestLines = new[]
{
"POST / HTTP/1.0\r\n",
$"Content-Length: {_dataLength}\r\n",
"\r\n"
};
public static IEnumerable<object[]> LargeUploadData
{
get
{
var maxRequestBufferSizeValues = new Tuple<long?, bool>[] {
// Smallest buffer that can hold a POST request line to the root.
Tuple.Create((long?)"POST / HTTP/1.1\r\n".Length, true),
// Smallest buffer that can hold a test request line without causing
// the server to hang waiting for the end of the request line or
// a header line.
Tuple.Create((long?)(_requestLines.Max(line => line.Length)), true),
// Small buffer, but large enough to hold all request headers.
Tuple.Create((long?)16 * 1024, true),
@ -186,6 +193,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{
options.Limits.MaxRequestLineSize = (int)maxRequestBufferSize;
}
if (maxRequestBufferSize.HasValue &&
maxRequestBufferSize.Value < options.Limits.MaxRequestHeadersTotalSize)
{
options.Limits.MaxRequestHeadersTotalSize = (int)maxRequestBufferSize;
}
})
.UseContentRoot(Directory.GetCurrentDirectory())
.Configure(app => app.Run(async context =>
@ -246,9 +259,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize: 1024, leaveOpen: true))
{
await writer.WriteAsync("POST / HTTP/1.0\r\n");
await writer.WriteAsync($"Content-Length: {contentLength}\r\n");
await writer.WriteAsync("\r\n");
foreach (var line in _requestLines)
{
await writer.WriteAsync(line);
}
}
}
}

View File

@ -24,25 +24,30 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public void StartWithNonPositiveThreadCountThrows(int threadCount)
{
var testLogger = new TestApplicationErrorLogger { ThrowOnCriticalErrors = false };
var server = CreateServer(new KestrelServerOptions() { ThreadCount = threadCount }, testLogger);
var exception = Assert.Throws<ArgumentOutOfRangeException>(() => StartDummyApplication(server));
using (var server = CreateServer(new KestrelServerOptions() { ThreadCount = threadCount }, testLogger))
{
var exception = Assert.Throws<ArgumentOutOfRangeException>(() => StartDummyApplication(server));
Assert.Equal("threadCount", exception.ParamName);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
Assert.Equal("threadCount", exception.ParamName);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
}
}
[Fact]
public void StartWithInvalidAddressThrows()
{
var testLogger = new TestApplicationErrorLogger { ThrowOnCriticalErrors = false };
var server = CreateServer(new KestrelServerOptions(), testLogger);
server.Features.Get<IServerAddressesFeature>().Addresses.Add("http:/asdf");
var exception = Assert.Throws<FormatException>(() => StartDummyApplication(server));
using (var server = CreateServer(new KestrelServerOptions(), testLogger))
{
server.Features.Get<IServerAddressesFeature>().Addresses.Add("http:/asdf");
Assert.Contains("Invalid URL", exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
var exception = Assert.Throws<FormatException>(() => StartDummyApplication(server));
Assert.Contains("Invalid URL", exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
}
}
[Theory]
@ -77,14 +82,37 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
options.Limits.MaxRequestBufferSize = maxRequestBufferSize;
options.Limits.MaxRequestLineSize = maxRequestLineSize;
var server = CreateServer(options, testLogger);
using (var server = CreateServer(options, testLogger))
{
var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server));
var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server));
Assert.Equal(
$"Maximum request buffer size ({maxRequestBufferSize}) must be greater than or equal to maximum request line size ({maxRequestLineSize}).",
exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
}
}
Assert.Equal(
$"Maximum request buffer size ({maxRequestBufferSize}) must be greater than or equal to maximum request line size ({maxRequestLineSize}).",
exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
[Theory]
[InlineData(1, 2)]
[InlineData(int.MaxValue - 1, int.MaxValue)]
public void StartWithMaxRequestBufferSizeLessThanMaxRequestHeadersTotalSizeThrows(long maxRequestBufferSize, int maxRequestHeadersTotalSize)
{
var testLogger = new TestApplicationErrorLogger { ThrowOnCriticalErrors = false };
var options = new KestrelServerOptions();
options.Limits.MaxRequestBufferSize = maxRequestBufferSize;
options.Limits.MaxRequestLineSize = (int)maxRequestBufferSize;
options.Limits.MaxRequestHeadersTotalSize = maxRequestHeadersTotalSize;
using (var server = CreateServer(options, testLogger))
{
var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server));
Assert.Equal(
$"Maximum request buffer size ({maxRequestBufferSize}) must be greater than or equal to maximum request headers size ({maxRequestHeadersTotalSize}).",
exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
}
}
[Fact]