Skip to content

Commit 9f8ce33

Browse files
authored
JCR-5233: commons-fileupload (1.6) restricts header size in upload pa… (#357)
1 parent 0690b00 commit 9f8ce33

2 files changed

Lines changed: 20 additions & 45 deletions

File tree

jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class HttpMultipartPost {
4545
private final Map<String, List<FileItem>> nameToItems = new LinkedHashMap<String, List<FileItem>>();
4646
private final Set<String> fileParamNames = new HashSet<String>();
4747

48+
// <= 0 (default -1) -> Jackrabbit applies 4096 (overrides cfup 1.6's current 512-byte default);
49+
// positive -> exact value in bytes. Set to 512 to restore the library's own default.
4850
private final int PARTHEADERSIZEMAX = Integer.getInteger("jackrabbit-server-PartHeaderSizeMax", -1);
4951

5052
private boolean initialized;
@@ -69,6 +71,9 @@ private void extractMultipart(HttpServletRequest request, File tmpDir)
6971
ServletFileUpload upload = new ServletFileUpload(getFileItemFactory(tmpDir));
7072
if (PARTHEADERSIZEMAX > 0) {
7173
upload.setPartHeaderSizeMax(PARTHEADERSIZEMAX);
74+
} else {
75+
// override the default limit of 512 in commons-fileupload 1.6
76+
upload.setPartHeaderSizeMax(4096);
7277
}
7378
// make sure the content disposition headers are read with the charset
7479
// specified in the request content type (or UTF-8 if no charset is specified).

jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/util/RequestDataTest.java

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import static org.junit.Assert.assertTrue;
3535
import static org.mockito.Mockito.*;
3636

37-
3837
import javax.servlet.ServletInputStream;
3938
import java.io.ByteArrayInputStream;
4039
import java.io.IOException;
@@ -210,70 +209,41 @@ public void testMultipartPostWithShorterFilename() throws Exception {
210209
}
211210
}
212211

213-
@Test(expected=IOException.class)
212+
@Test(expected = IOException.class)
214213
public void testMultipartPostWithExtremelyLongFilename() throws Exception {
215-
buildRequestWithFilenameOfVaryingLength(1000);
214+
// header bytes ~= filename length + ~107; at 5000 chars this far exceeds the 4096 default
215+
buildRequestWithFilenameOfVaryingLength(5000);
216216
File testTmpDir = tempFolder.newFolder("jackrabbit_long_filename");
217+
new RequestData(mockRequest, testTmpDir); // must throw IOException
218+
}
219+
220+
@Test
221+
public void testMultipartPostWithLongFilenameUnderNewDefault() throws Exception {
222+
buildRequestWithFilenameOfVaryingLength(3800); // above 512, below 4096
223+
File testTmpDir = tempFolder.newFolder("jackrabbit_medium_filename");
217224
RequestData requestData = new RequestData(mockRequest, testTmpDir);
218225
try {
219-
assertTrue(
220-
requestData.getParameter("fileUpload").length() > 950);
226+
assertTrue(requestData.getParameter("fileUpload").length() > 3800);
221227
} finally {
222228
requestData.dispose();
223229
}
224230
}
225231

226232
@Test
227-
public void testMultipartPostWithExtremelyLongFilenameNButHigherConfig() throws Exception {
233+
public void testMultipartPostWithExtremelyLongFilenameWithHigherConfig() throws Exception {
228234
try {
229-
System.setProperty("jackrabbit-server-PartHeaderSizeMax", "2048");
230-
buildRequestWithFilenameOfVaryingLength(1000);
235+
System.setProperty("jackrabbit-server-PartHeaderSizeMax", "8192");
236+
buildRequestWithFilenameOfVaryingLength(7500);
231237
File testTmpDir = tempFolder.newFolder("jackrabbit_long_filename");
232238
RequestData requestData = new RequestData(mockRequest, testTmpDir);
233239
try {
234240
assertTrue(
235-
requestData.getParameter("fileUpload").length() > 950);
241+
requestData.getParameter("fileUpload").length() > 7500);
236242
} finally {
237243
requestData.dispose();
238244
}
239245
} finally {
240246
System.clearProperty("jackrabbit-server-PartHeaderSizeMax");
241247
}
242248
}
243-
244-
/**
245-
* Assures special Unicode (Non-ASCII) symbols preserve structural state during text decoding.
246-
*/
247-
// @Test
248-
public void testMultipartPostWithNonAsciiCharacters() throws Exception {
249-
File testTmpDir = tempFolder.newFolder("jackrabbit_non_ascii");
250-
String boundary = "----MockBoundaryNonAscii";
251-
String nonAsciiValue = "テスト_ü_é_ñ_value";
252-
String nonAsciiFilename = "マニュアル_doc.pdf";
253-
254-
String body = "--" + boundary + "\r\n" +
255-
"Content-Disposition: form-data; name=\"unicodeField\"\r\n\r\n" +
256-
nonAsciiValue + "\r\n" +
257-
"--" + boundary + "\r\n" +
258-
"Content-Disposition: form-data; name=\"unicodeFile\"; filename=\"" + nonAsciiFilename + "\"\r\n" +
259-
"Content-Type: application/pdf\r\n\r\n" +
260-
"%PDF-Mock-Bytes\r\n" +
261-
"--" + boundary + "--\r\n";
262-
263-
byte[] payloadBytes = body.getBytes(StandardCharsets.UTF_8);
264-
265-
when(mockRequest.getMethod()).thenReturn("POST");
266-
when(mockRequest.getContentType()).thenReturn("multipart/form-data; boundary=" + boundary);
267-
lenient().when(mockRequest.getCharacterEncoding()).thenReturn("UTF-8");
268-
when(mockRequest.getInputStream()).thenReturn(createServletInputStream(payloadBytes));
269-
270-
RequestData requestData = new RequestData(mockRequest, testTmpDir);
271-
try {
272-
String parsedValue = requestData.getParameter("unicodeField");
273-
assertEquals("Unicode decoding was corrupted inside the parsing sequence", nonAsciiValue, parsedValue);
274-
assertNotNull("Non-ASCII file part metadata parsing must complete successfully", requestData.getParameter("unicodeFile"));
275-
} finally {
276-
requestData.dispose();
277-
}
278-
}
279249
}

0 commit comments

Comments
 (0)