diff --git a/src/Http/Http/src/Features/FormFeature.cs b/src/Http/Http/src/Features/FormFeature.cs index e758b1b0354c1a6713fccdf58a7e6adc33efc0da..173904e8c19496a93dcc8e6b913e5f8f58f2fd12 100644 --- a/src/Http/Http/src/Features/FormFeature.cs +++ b/src/Http/Http/src/Features/FormFeature.cs @@ -184,6 +184,7 @@ namespace Microsoft.AspNetCore.Http.Features else if (HasMultipartFormContentType(contentType)) { var formAccumulator = new KeyValueAccumulator(); + var nonFormOrFileContentDispositionCount = 0; var boundary = GetBoundary(contentType, _options.MultipartBoundaryLengthLimit); var multipartReader = new MultipartReader(boundary, _request.Body) @@ -259,7 +260,11 @@ namespace Microsoft.AspNetCore.Http.Features } else { - System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + section.ContentDisposition); + if (nonFormOrFileContentDispositionCount++ >= _options.ValueCountLimit) + { + throw new InvalidDataException($"Unrecognized Content-Disposition. Form value count limit {_options.ValueCountLimit} exceeded."); + + } } section = await multipartReader.ReadNextSectionAsync(cancellationToken); diff --git a/src/Http/Http/test/Features/FormFeatureTests.cs b/src/Http/Http/test/Features/FormFeatureTests.cs index 9426ce6dd1b2a6b4a347834cc023285b7b770a94..67873e223c4d2fb7739553ce5493c08080fba34b 100644 --- a/src/Http/Http/test/Features/FormFeatureTests.cs +++ b/src/Http/Http/test/Features/FormFeatureTests.cs @@ -165,6 +165,12 @@ namespace Microsoft.AspNetCore.Http.Features InvalidContentDispositionValue + "\r\n" + "\r\n" + +"Foo\r\n"; + + private const string MultipartFormFileNonFormOrFileContentDispositionValue = "--WebKitFormBoundary5pDRpGheQXaM8k3T\r\n" + +"Content-Disposition:x" + +"\r\n" + +"\r\n" + "Foo\r\n"; private const string MultipartFormWithField = @@ -468,6 +474,30 @@ InvalidContentDispositionValue + Assert.Equal("Form value count limit 2 exceeded.", exception.Message); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ReadFormAsync_NonFormOrFieldContentDisposition_ValueCountLimitExceeded_Throw(bool bufferRequest) + { + var formContent = new List<byte>(); + formContent.AddRange(Encoding.UTF8.GetBytes(MultipartFormFileNonFormOrFileContentDispositionValue)); + formContent.AddRange(Encoding.UTF8.GetBytes(MultipartFormFileNonFormOrFileContentDispositionValue)); + formContent.AddRange(Encoding.UTF8.GetBytes(MultipartFormFileNonFormOrFileContentDispositionValue)); + formContent.AddRange(Encoding.UTF8.GetBytes(MultipartFormEnd)); + + var context = new DefaultHttpContext(); + var responseFeature = new FakeResponseFeature(); + context.Features.Set<IHttpResponseFeature>(responseFeature); + context.Request.ContentType = MultipartContentType; + context.Request.Body = new NonSeekableReadStream(formContent.ToArray()); + + IFormFeature formFeature = new FormFeature(context.Request, new FormOptions() { BufferBody = bufferRequest, ValueCountLimit = 2 }); + context.Features.Set<IFormFeature>(formFeature); + + var exception = await Assert.ThrowsAsync<InvalidDataException>(() => context.Request.ReadFormAsync()); + Assert.Equal("Unrecognized Content-Disposition. Form value count limit 2 exceeded.", exception.Message); + } + [Theory] [InlineData(true)] [InlineData(false)]