Repository navigation
Conversation
RFC 9110 5.6.6 defines `parameters = *( OWS ";" OWS [ parameter ] )`, so an empty parameter slot -- a trailing ';' or ';;' -- is valid and carries no information. userver rejected such a Content-Type or Content-Disposition with `400 invalid body of multipart/form-data request`, without even looking at the request body. The mandatory-parameter grammar userver implements comes from RFC 2616 3.7 and RFC 7231 3.1.1.1, both obsoleted by RFC 9110 in June 2022. A valueless parameter (a bare token in a parameter slot) remains an error, as do a Content-Type without `boundary` and a Content-Disposition without `name`.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes: #1357
A
multipart/form-datarequest whoseContent-Typecontains an empty parameterslot — a trailing
;, or;;— is rejected with400 invalid body of multipart/form-data request, even when the body isperfectly valid. The same applies to a part's
Content-Disposition. RFC 9110§5.6.6 explicitly permits empty parameter slots.
Why
RFC 9110 §5.6.6, via
§8.3.1:
The
[ parameter ]brackets make an empty slot valid, somultipart/form-data; boundary=zzz;is a conformingContent-Typeand uservermust accept it.
This is a change from the obsoleted specs: RFC 2068 §3.7, RFC 2616 §3.7 and
RFC 7231 §3.1.1.1 all had the parameter mandatory
(
*( OWS ";" OWS parameter )), so under those a trailing;really was agrammar violation. RFC 9110 (June 2022) obsoletes all three.
There is also no sender-side prohibition to fall back on: §5.6.1.1's "a sender
MUST NOT generate empty list elements" is scoped to the comma-list (
#)construct, not to
parameters. A client sending this is not misbehaving.How
ParseMultipartFormDataandParseContentDispositioneach have a parameter loopthat calls
ReadTokenafter consuming a;and treats an empty token as fatal.Both now treat it as a valid no-op, by inverting the existing
if (!param_name.empty())into a guard clause:The rest of the production diff is the resulting dedent of the former
ifbody —no logic change there, so
?w=1collapses it to the four lines above, twice.The RFC-citation comment follows the existing convention in this file, which
already annotates
ReadTokenandReadHeaderValuewith the grammar rule andlink they implement.
Termination is unaffected.
SkipSymbol(str, ';')runs at the top of the loopbefore
ReadToken, so every iteration consumes at least one character, and anynon-
;garbage still fails on thatSkipSymbol.What still fails
The change is deliberately narrow — an empty slot is accepted, nothing else:
multipart/form-data; boundary=zzz; novalue[ parameter ]is a completename=valueor nothing; a bare token is neitherContent-Disposition: form-data; name="a"; novaluemultipart/form-data;;boundaryparameterContent-Disposition: form-data;nameparameterEach of these is pinned by
ParseInvalidParametersStillFailso the leniencycannot widen unnoticed later.
Tests
Three tests in
multipart_form_data_parser_test.cpp:ParseEmptyContentTypeParameter— seven content types: trailing;,;;,; ;with spaces, an empty slot in the middle,;;directly after the mediatype, and with a
charsetparameter present. All expect the arg to parse.ParseEmptyContentDispositionParameter— the same shapes in a part'sContent-Disposition.ParseInvalidParametersStillFail— the negative guard above.Verified locally:
sub-cases; with it they pass
ParseInvalidParametersStillFailpasses either wayMultipartFormDataParsertests are unaffectedImpact
Requests that userver rejects today with
400 invalid body of multipart/form-data requestandBad Content-Type: empty attribute name(orBad Content-Disposition: empty attribute name) now reach the handler withtheir form arguments parsed. No currently-accepted input changes behaviour, and
no test asserted the old rejection.