Reject MIME type parameters differing only in case - #37008
Conversation
|
Hi @junhyeong9812! Since this PR was opened, the MIME type parser was rewritten as a state machine parser ( As a result, your changes to the old parser method will conflict. To resolve this and make the check case-insensitive, the accumulator map instantiation in private void putParameter(String name, String value) {
if (this.parameters == null) {
this.parameters = new LinkedCaseInsensitiveMap<>(4, Locale.ROOT);
}
if (this.parameters.put(name, value) != null) {
throw new InvalidMimeTypeException(this.input, "duplicate parameter '" + name + "=" + value + "'");
}
} |
MIME type parameter names are case-insensitive, but MimeTypeParser accumulates parameters in a case-sensitive LinkedHashMap. As a result, duplicate parameters differing only in case (such as "charset" and "CHARSET") were not rejected and were silently collapsed to the last value by the case-insensitive parameter map of MimeType. Accumulate parameters in a LinkedCaseInsensitiveMap so that duplicates differing only in case map to the same key and are rejected consistently with exact duplicates. Signed-off-by: junhyeong9812 <pickjog@gmail.com> Co-authored-by: Yash <190389954+yashsiwacha@users.noreply.github.com>
0c01e41 to
019c822
Compare
|
Thanks for the heads-up @yashsiwacha! I've rebased the branch onto the latest main and reworked the fix against the new state machine parser as you suggested: the accumulator map in |
Overview
MimeTypeUtilsrejects duplicate MIME type parameters (gh-36841), but the check is case-sensitive while MIME parameter names are case-insensitive. As a result, duplicates that differ only in case (for examplecharsetandCHARSET) slip through and are silently collapsed to the last value. This aligns the duplicate check with the case-insensitive nature of parameter names.Since this PR was first opened, the parser was rewritten as a state machine (
MimeTypeParser, commit 0799920); this PR has been reworked against the new parser accordingly.Problem
When parsing parameters,
MimeTypeParser.putParameter(...)accumulates them in aLinkedHashMapand rejects duplicates by throwing whenMap#putreturns a previous value:Because a
LinkedHashMaptreatscharsetandCHARSETas distinct keys, a case-variant duplicate never triggers the check:text/plain;dupe="1";dupe="2"InvalidMimeTypeException)text/plain;dupe="1";DUPE="2""2"This is inconsistent: MIME parameter names are case-insensitive (RFC 2045), and
MimeTypeitself stores parameters in aLinkedCaseInsensitiveMapso thatgetParameter("CHARSET")andgetParameter("charset")resolve to the same value. RFC 6838 section 4.3 (cited by gh-36841) treats duplicate parameters as an error, so a case-only variant is logically the same duplicate.Fix
Accumulate parameters in a
LinkedCaseInsensitiveMapso that a case-variant duplicate maps to the same key, causingputto return the previous value and the existing check to reject it:Locale.ROOTmatches howMimeTypebuilds its own parameter map, keeping case-insensitive comparison locale-independent. The finalMimeTypeis unaffected: its constructor re-copies the parameters into its ownLinkedCaseInsensitiveMap, and for non-duplicate input the accumulating map behaves the same as before (same keys, values, and iteration order). Only the duplicate-detection sensitivity changes.Note on impact
This is a parsing behavior change:
Content-Type/Accept-style strings that repeat a parameter with different casing now throwInvalidMimeTypeExceptioninstead of parsing successfully. This matches the intent of gh-36841 and the case-insensitive contract of parameter names; valid MIME types are unaffected.