Skip to content

Commit 25e8395

Browse files
committed
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
1 parent 148b7fd commit 25e8395

4 files changed

Lines changed: 13 additions & 3 deletions

File tree

spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ else if (ch == '"' && mimeType.charAt(nextIndex - 1) != '\\') {
252252
if (eqIndex >= 0) {
253253
String attribute = parameter.substring(0, eqIndex).trim();
254254
String value = parameter.substring(eqIndex + 1).trim();
255-
parameters.put(attribute, value);
255+
if (parameters.put(attribute, value) != null) {
256+
throw new InvalidMimeTypeException(mimeType, "duplicate parameter '" + parameter + "'");
257+
}
256258
}
257259
}
258260
index = nextIndex;

spring-core/src/test/java/org/springframework/util/MimeTypeTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import static org.assertj.core.api.Assertions.assertThat;
3333
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
3434
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
35+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3536

3637
/**
3738
* Tests for {@link MimeType}.
@@ -116,6 +117,13 @@ void parseParameterWithQuotedPair() {
116117
assertThat(mimeType.getParameter("twelve")).isEqualTo("\"1\\\"2\"");
117118
}
118119

120+
@Test
121+
void rejectsDuplicateParameter() {
122+
String s = "text/plain;dupe=\"1\";dupe=\"2\"";
123+
assertThatThrownBy(() -> MimeType.valueOf(s)).isInstanceOf(InvalidMimeTypeException.class)
124+
.hasMessageContaining("Invalid mime type \"text/plain;dupe=\"1\";dupe=\"2\"\": duplicate parameter 'dupe=\"2\"'");
125+
}
126+
119127
@Test
120128
void withConversionService() {
121129
ConversionService conversionService = new DefaultConversionService();

spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void contentTypeMultipleCalls() {
237237

238238
@Test // SPR-12677
239239
void setContentTypeHeaderWithMoreComplexCharsetSyntax() {
240-
String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foo=bar";
240+
String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foobar=bar";
241241
request.addHeader(HttpHeaders.CONTENT_TYPE, contentType);
242242
assertThat(request.getContentType()).isEqualTo(contentType);
243243
assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(contentType);

spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ void shouldSetUtf8EncodingForJson() {
116116

117117
@Test // SPR-12677
118118
void shouldSetEncodingWithComplexContentTypeSyntax() {
119-
String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foo=bar";
119+
String contentType = "test/plain;charset=\"utf-8\";foo=\"charset=bar\";foocharset=bar;foobar=bar";
120120
response.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
121121
assertThat(response.getContentType()).isEqualTo(contentType);
122122
assertThat(response.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(contentType);

0 commit comments

Comments
 (0)