From 25e8395df804e9fc31fa4f005535113b4e8c6b21 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 26 May 2026 17:53:28 +0200 Subject: [PATCH] Reject duplicate MIME type parameters Prior to this commit, MIME type parsing in Spring would allow duplicate parameters like "text/plain; dupe=1; dupe=2", effectively retaining the latest value and ignoring the first. RFC 6838 4.3 states that this should be treated as an error and this commit ensures that this is the case. Closes gh-36841 --- .../main/java/org/springframework/util/MimeTypeUtils.java | 4 +++- .../test/java/org/springframework/util/MimeTypeTests.java | 8 ++++++++ .../mock/web/MockHttpServletRequestTests.java | 2 +- .../mock/web/MockHttpServletResponseTests.java | 2 +- 4 files changed, 13 insertions(+), 3 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 24add7f4f3d..55f76d94820 100644 --- a/spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java +++ b/spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java @@ -252,7 +252,9 @@ public abstract class MimeTypeUtils { if (eqIndex >= 0) { String attribute = parameter.substring(0, eqIndex).trim(); String value = parameter.substring(eqIndex + 1).trim(); - parameters.put(attribute, value); + if (parameters.put(attribute, value) != null) { + throw new InvalidMimeTypeException(mimeType, "duplicate parameter '" + parameter + "'"); + } } } index = nextIndex; 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 6346b8ec540..cffa8d31e5f 100644 --- a/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java +++ b/spring-core/src/test/java/org/springframework/util/MimeTypeTests.java @@ -32,6 +32,7 @@ import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Tests for {@link MimeType}. @@ -116,6 +117,13 @@ class MimeTypeTests { assertThat(mimeType.getParameter("twelve")).isEqualTo("\"1\\\"2\""); } + @Test + void rejectsDuplicateParameter() { + 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(); diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java index e416e3fb44d..5184b5bf8cf 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java @@ -237,7 +237,7 @@ class MockHttpServletRequestTests { @Test // SPR-12677 void setContentTypeHeaderWithMoreComplexCharsetSyntax() { - String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foo=bar"; + String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foobar=bar"; request.addHeader(HttpHeaders.CONTENT_TYPE, contentType); assertThat(request.getContentType()).isEqualTo(contentType); assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(contentType); diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java index baf67c88f69..ef0df3a1719 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java @@ -116,7 +116,7 @@ class MockHttpServletResponseTests { @Test // SPR-12677 void shouldSetEncodingWithComplexContentTypeSyntax() { - String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foo=bar"; + String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foobar=bar"; response.setHeader(HttpHeaders.CONTENT_TYPE, contentType); assertThat(response.getContentType()).isEqualTo(contentType); assertThat(response.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(contentType);