You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
res.format() normalizes its keys through acceptParams() in lib/utils.js, which parses each ;-separated parameter by scanning for the next raw ; to know where the value ends. That breaks when the value is a quoted string that legitimately contains a ;, e.g.:
text/plain; foo="a;b"; bar=baz
Right now this parses foo as "a and silently drops the rest (b"), because the parser has no idea it's inside quotes when it hits that semicolon. I ran into this while poking around res.format() and figured it was worth fixing properly rather than patching around it.
The fix adds a small helper, indexOfUnquoted(), that walks the string and ignores delimiters found inside a quoted span (also handles an escaped \" so it doesnt end the quote early), and swap it in for the one indexOf(';') call that needed it. Everything else about acceptParams is untouched — same behavior for plain types, missing =, malformed params, etc.
Added two tests in test/utils.js covering the quoted-semicolon case and the escaped-quote case. Ran the full suite locally (1263 passing) and lint is clean.
I haven't reviewed this and don't plan to, but here are some relevant definitions from RFC 9110 (only most important parts, follow the links for full text):
Each media-range might be followed by optional applicable media type parameters (e.g., charset), followed by an optional "q" parameter for indicating a relative weight (Section 12.4.2).
Previous specifications allowed additional extension parameters to appear after the weight parameter. The accept extension grammar (accept-params, accept-ext) has been removed because it had a complicated definition, was not being used in practice, and is more easily deployed through new header fields. Senders using weights SHOULD send "q" last (after all media-range parameters). Recipients SHOULD process any parameter named "q" as weight, regardless of parameter ordering.
A parameter value that matches the token production can be transmitted either as a token or within a quoted-string. The quoted and unquoted values are equivalent.
The backslash octet ("\") can be used as a single-octet quoting mechanism within quoted-string and comment constructs. Recipients that process the value of a quoted-string MUST handle a quoted-pair as if it were replaced by the octet following the backslash.
A sender SHOULD NOT generate a quoted-pair in a quoted-string except where necessary to quote DQUOTE and backslash octets occurring within that string.
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
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.
res.format()normalizes its keys throughacceptParams()inlib/utils.js, which parses each;-separated parameter by scanning for the next raw;to know where the value ends. That breaks when the value is a quoted string that legitimately contains a;, e.g.:Right now this parses
fooas"aand silently drops the rest (b"), because the parser has no idea it's inside quotes when it hits that semicolon. I ran into this while poking aroundres.format()and figured it was worth fixing properly rather than patching around it.The fix adds a small helper,
indexOfUnquoted(), that walks the string and ignores delimiters found inside a quoted span (also handles an escaped\"so it doesnt end the quote early), and swap it in for the oneindexOf(';')call that needed it. Everything else aboutacceptParamsis untouched — same behavior for plain types, missing=, malformed params, etc.Added two tests in
test/utils.jscovering the quoted-semicolon case and the escaped-quote case. Ran the full suite locally (1263 passing) and lint is clean.