From 0c01e410203647e39bdda2f5e828fc5ebd8fed75 Mon Sep 17 00:00:00 2001 From: junhyeong9812 Date: Mon, 6 Jul 2026 22:16:00 +0900 Subject: [PATCH] Reject MIME type parameters differing only in case MIME type parameter names are case-insensitive, but the duplicate parameter check added in gh-36841 accumulated parameters in a case-sensitive map. As a result, duplicates differing only in case (such as "charset" and "CHARSET") were not rejected and were silently collapsed to the last value. Accumulate parameters in a LinkedCaseInsensitiveMap so that such duplicates map to the same key and are rejected consistently, matching the case-insensitive map already used by MimeType for parameter storage. Signed-off-by: junhyeong9812 --- .../main/java/org/springframework/util/MimeTypeUtils.java | 6 ++++-- .../test/java/org/springframework/util/MimeTypeTests.java | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java b/spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java index 214139d50165..85838a79288a 100644 --- a/spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java +++ b/spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java @@ -23,8 +23,8 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.function.BiPredicate; @@ -246,7 +246,9 @@ else if (ch == '"' && (nextIndex == 0 || mimeType.charAt(nextIndex - 1) != '\\') String parameter = mimeType.substring(index + 1, nextIndex).trim(); if (parameter.length() > 0) { if (parameters == null) { - parameters = new LinkedHashMap<>(4); + // Parameter names are case-insensitive, so use a case-insensitive + // map in order to reject duplicates that differ only in case. + parameters = new LinkedCaseInsensitiveMap<>(4, Locale.ROOT); } int eqIndex = parameter.indexOf('='); if (eqIndex >= 0) { diff --git a/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java b/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java index 29cf7119b508..13ba1109c6f7 100644 --- a/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java +++ b/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java @@ -124,6 +124,13 @@ void rejectsDuplicateParameter() { .hasMessageContaining("Invalid mime type \"text/plain;dupe=\"1\";dupe=\"2\"\": duplicate parameter 'dupe=\"2\"'"); } + @Test + void rejectsDuplicateParameterWithDifferentCase() { + String s = "text/plain;dupe=\"1\";DUPE=\"2\""; + assertThatThrownBy(() -> MimeType.valueOf(s)).isInstanceOf(InvalidMimeTypeException.class) + .hasMessageContaining("Invalid mime type \"text/plain;dupe=\"1\";DUPE=\"2\"\": duplicate parameter 'DUPE=\"2\"'"); + } + @Test void withConversionService() { ConversionService conversionService = new DefaultConversionService();