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
This commit is contained in:
Brian Clozel
2026-05-26 17:53:28 +02:00
parent 148b7fd8f3
commit 25e8395df8
4 changed files with 13 additions and 3 deletions
@@ -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;
@@ -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();
@@ -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);
@@ -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);