Skip to content

Commit 163a606

Browse files
committed
When deserializing DiskFileItems ensure that the repository location, if any, is a valid one.
Patch provided by Arun Babu Neelicattu. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/fileupload/trunk@1507048 13f79535-47bb-0310-9956-ffa450edef68
1 parent e685ae4 commit 163a606

File tree

3 files changed

+126
-38
lines changed

3 files changed

+126
-38
lines changed

src/changes/changes.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ The <action> type attribute can be add,update,fix,remove.
4343
</properties>
4444

4545
<body>
46+
<release version="1.3.1" description="maintenance release" date="TBD">
47+
<action dev="markt" type="fix" due-to="Arun Babu Neelicattu" due-to-email="[email protected]">
48+
When deserializing DiskFileItems ensure that the repository location, if
49+
any, is a valid one.
50+
</action>
51+
</release>
52+
4653
<release version="1.3" description="maintenance release, JDK1.5 update" date="2013-03-27">
4754
<!-- important notes -->
4855
<action dev="markt" type="fix">

src/main/java/org/apache/commons/fileupload/disk/DiskFileItem.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,26 @@ private void readObject(ObjectInputStream in)
656656
// read values
657657
in.defaultReadObject();
658658

659+
/* One expected use of serialization is to migrate HTTP sessions
660+
* containing a DiskFileItem between JVMs. Particularly if the JVMs are
661+
* on different machines It is possible that the repository location is
662+
* not valid so validate it.
663+
*/
664+
if (repository != null) {
665+
if (repository.isDirectory()) {
666+
// Check path for nulls
667+
if (repository.getPath().contains("\0")) {
668+
throw new IOException(format(
669+
"The repository [%s] contains a null character",
670+
repository.getPath()));
671+
}
672+
} else {
673+
throw new IOException(format(
674+
"The repository [%s] is not a directory",
675+
repository.getAbsolutePath()));
676+
}
677+
}
678+
659679
OutputStream output = getOutputStream();
660680
if (cachedContent != null) {
661681
output.write(cachedContent);

src/test/java/org/apache/commons/fileupload/DiskFileItemSerializeTest.java

Lines changed: 99 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import java.io.ByteArrayInputStream;
2626
import java.io.ByteArrayOutputStream;
27+
import java.io.File;
2728
import java.io.IOException;
2829
import java.io.ObjectInputStream;
2930
import java.io.ObjectOutputStream;
@@ -51,14 +52,10 @@ public class DiskFileItemSerializeTest {
5152
private static final int threshold = 16;
5253

5354
/**
54-
* Test creation of a field for which the amount of data falls below the
55-
* configured threshold.
55+
* Helper method to test creation of a field when a repository is used.
5656
*/
57-
@Test
58-
public void testBelowThreshold() throws Exception {
59-
// Create the FileItem
60-
byte[] testFieldValueBytes = createContentBytes(threshold - 1);
61-
FileItem item = createFileItem(testFieldValueBytes);
57+
public void testInMemoryObject(byte[] testFieldValueBytes, File repository) {
58+
FileItem item = createFileItem(testFieldValueBytes, repository);
6259

6360
// Check state is as expected
6461
assertTrue("Initial: in memory", item.isInMemory());
@@ -75,6 +72,24 @@ public void testBelowThreshold() throws Exception {
7572
// Compare FileItem's (except byte[])
7673
compareFileItems(item, newItem);
7774
}
75+
76+
/**
77+
* Helper method to test creation of a field.
78+
*/
79+
private void testInMemoryObject(byte[] testFieldValueBytes) {
80+
testInMemoryObject(testFieldValueBytes, null);
81+
}
82+
83+
/**
84+
* Test creation of a field for which the amount of data falls below the
85+
* configured threshold.
86+
*/
87+
@Test
88+
public void testBelowThreshold() throws Exception {
89+
// Create the FileItem
90+
byte[] testFieldValueBytes = createContentBytes(threshold - 1);
91+
testInMemoryObject(testFieldValueBytes);
92+
}
7893

7994
/**
8095
* Test creation of a field for which the amount of data equals the
@@ -84,23 +99,7 @@ public void testBelowThreshold() throws Exception {
8499
public void testThreshold() throws Exception {
85100
// Create the FileItem
86101
byte[] testFieldValueBytes = createContentBytes(threshold);
87-
FileItem item = createFileItem(testFieldValueBytes);
88-
89-
// Check state is as expected
90-
assertTrue("Initial: in memory", item.isInMemory());
91-
assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
92-
compareBytes("Initial", item.get(), testFieldValueBytes);
93-
94-
95-
// Serialize & Deserialize
96-
FileItem newItem = (FileItem)serializeDeserialize(item);
97-
98-
// Test deserialized content is as expected
99-
assertTrue("Check in memory", newItem.isInMemory());
100-
compareBytes("Check", testFieldValueBytes, newItem.get());
101-
102-
// Compare FileItem's (except byte[])
103-
compareFileItems(item, newItem);
102+
testInMemoryObject(testFieldValueBytes);
104103
}
105104

106105
/**
@@ -128,6 +127,41 @@ public void testAboveThreshold() throws Exception {
128127
// Compare FileItem's (except byte[])
129128
compareFileItems(item, newItem);
130129
}
130+
131+
/**
132+
* Test serialization and deserialization when repository is not null.
133+
*/
134+
@Test
135+
public void testValidRepository() throws Exception {
136+
// Create the FileItem
137+
byte[] testFieldValueBytes = createContentBytes(threshold);
138+
File repository = new File(System.getProperty("java.io.tmpdir"));
139+
testInMemoryObject(testFieldValueBytes, repository);
140+
}
141+
142+
/**
143+
* Test deserialization fails when repository is not valid.
144+
*/
145+
@Test(expected=IOException.class)
146+
public void testInvalidRepository() throws Exception {
147+
// Create the FileItem
148+
byte[] testFieldValueBytes = createContentBytes(threshold);
149+
File repository = new File(System.getProperty("java.io.tmpdir") + "file");
150+
FileItem item = createFileItem(testFieldValueBytes, repository);
151+
deserialize(serialize(item));
152+
}
153+
154+
/**
155+
* Test deserialization fails when repository contains a null character.
156+
*/
157+
@Test(expected=IOException.class)
158+
public void testInvalidRepositoryWithNullChar() throws Exception {
159+
// Create the FileItem
160+
byte[] testFieldValueBytes = createContentBytes(threshold);
161+
File repository = new File(System.getProperty("java.io.tmpdir") + "\0");
162+
FileItem item = createFileItem(testFieldValueBytes, repository);
163+
deserialize(serialize(item));
164+
}
131165

132166
/**
133167
* Compare FileItem's (except the byte[] content)
@@ -169,10 +203,10 @@ private byte[] createContentBytes(int size) {
169203
}
170204

171205
/**
172-
* Create a FileItem with the specfied content bytes.
206+
* Create a FileItem with the specfied content bytes and repository.
173207
*/
174-
private FileItem createFileItem(byte[] contentBytes) {
175-
FileItemFactory factory = new DiskFileItemFactory(threshold, null);
208+
private FileItem createFileItem(byte[] contentBytes, File repository) {
209+
FileItemFactory factory = new DiskFileItemFactory(threshold, repository);
176210
String textFieldName = "textField";
177211

178212
FileItem item = factory.createItem(
@@ -192,33 +226,60 @@ private FileItem createFileItem(byte[] contentBytes) {
192226
return item;
193227

194228
}
229+
230+
/**
231+
* Create a FileItem with the specfied content bytes.
232+
*/
233+
private FileItem createFileItem(byte[] contentBytes) {
234+
return createFileItem(contentBytes, null);
235+
}
236+
237+
/**
238+
* Do serialization
239+
*/
240+
private ByteArrayOutputStream serialize(Object target) throws Exception {
241+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
242+
ObjectOutputStream oos = new ObjectOutputStream(baos);
243+
oos.writeObject(target);
244+
oos.flush();
245+
oos.close();
246+
return baos;
247+
}
248+
249+
/**
250+
* Do deserialization
251+
*/
252+
private Object deserialize(ByteArrayOutputStream baos) throws Exception {
253+
Object result = null;
254+
ByteArrayInputStream bais =
255+
new ByteArrayInputStream(baos.toByteArray());
256+
ObjectInputStream ois = new ObjectInputStream(bais);
257+
result = ois.readObject();
258+
bais.close();
195259

260+
return result;
261+
}
262+
196263
/**
197264
* Do serialization and deserialization.
198265
*/
199266
private Object serializeDeserialize(Object target) {
200267
// Serialize the test object
201-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
268+
ByteArrayOutputStream baos = null;
202269
try {
203-
ObjectOutputStream oos = new ObjectOutputStream(baos);
204-
oos.writeObject(target);
205-
oos.flush();
206-
oos.close();
270+
baos = serialize(target);
207271
} catch (Exception e) {
208272
fail("Exception during serialization: " + e);
209273
}
210-
274+
211275
// Deserialize the test object
212276
Object result = null;
213277
try {
214-
ByteArrayInputStream bais =
215-
new ByteArrayInputStream(baos.toByteArray());
216-
ObjectInputStream ois = new ObjectInputStream(bais);
217-
result = ois.readObject();
218-
bais.close();
278+
result = deserialize(baos);
219279
} catch (Exception e) {
220280
fail("Exception during deserialization: " + e);
221281
}
282+
222283
return result;
223284
}
224285

0 commit comments

Comments
 (0)