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
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f653b9b..974f97f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -43,6 +43,13 @@
   </properties>
 
   <body>
+    <release version="1.3.1" description="maintenance release" date="TBD">
+      <action dev="markt" type="fix" due-to="Arun Babu Neelicattu" due-to-email="abn@redhat.com">
+        When deserializing DiskFileItems ensure that the repository location, if
+        any, is a valid one.
+      </action>
+    </release>
+    
     <release version="1.3" description="maintenance release, JDK1.5 update" date="2013-03-27">
       <!-- important notes -->
       <action dev="markt" type="fix">
diff --git a/src/main/java/org/apache/commons/fileupload/disk/DiskFileItem.java b/src/main/java/org/apache/commons/fileupload/disk/DiskFileItem.java
index 613c863..55c7daa 100644
--- a/src/main/java/org/apache/commons/fileupload/disk/DiskFileItem.java
+++ b/src/main/java/org/apache/commons/fileupload/disk/DiskFileItem.java
@@ -656,6 +656,26 @@
         // read values
         in.defaultReadObject();
 
+        /* One expected use of serialization is to migrate HTTP sessions
+         * containing a DiskFileItem between JVMs. Particularly if the JVMs are
+         * on different machines It is possible that the repository location is
+         * not valid so validate it.
+         */
+        if (repository != null) {
+            if (repository.isDirectory()) {
+                // Check path for nulls
+                if (repository.getPath().contains("\0")) {
+                    throw new IOException(format(
+                            "The repository [%s] contains a null character",
+                            repository.getPath()));
+                }
+            } else {
+                throw new IOException(format(
+                        "The repository [%s] is not a directory",
+                        repository.getAbsolutePath()));
+            }
+        }
+
         OutputStream output = getOutputStream();
         if (cachedContent != null) {
             output.write(cachedContent);
diff --git a/src/test/java/org/apache/commons/fileupload/DiskFileItemSerializeTest.java b/src/test/java/org/apache/commons/fileupload/DiskFileItemSerializeTest.java
index 8a77fd6..e823f74 100644
--- a/src/test/java/org/apache/commons/fileupload/DiskFileItemSerializeTest.java
+++ b/src/test/java/org/apache/commons/fileupload/DiskFileItemSerializeTest.java
@@ -24,6 +24,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -51,14 +52,10 @@
     private static final int threshold = 16;
 
     /**
-     * Test creation of a field for which the amount of data falls below the
-     * configured threshold.
+     * Helper method to test creation of a field when a repository is used.
      */
-    @Test
-    public void testBelowThreshold() throws Exception {
-        // Create the FileItem
-        byte[] testFieldValueBytes = createContentBytes(threshold - 1);
-        FileItem item = createFileItem(testFieldValueBytes);
+    public void testInMemoryObject(byte[] testFieldValueBytes, File repository) {
+        FileItem item = createFileItem(testFieldValueBytes, repository);
 
         // Check state is as expected
         assertTrue("Initial: in memory", item.isInMemory());
@@ -75,6 +72,24 @@
         // Compare FileItem's (except byte[])
         compareFileItems(item, newItem);
     }
+    
+    /**
+     * Helper method to test creation of a field.
+     */
+    private void testInMemoryObject(byte[] testFieldValueBytes) {
+        testInMemoryObject(testFieldValueBytes, null);
+    }
+    
+    /**
+     * Test creation of a field for which the amount of data falls below the
+     * configured threshold.
+     */
+    @Test
+    public void testBelowThreshold() throws Exception {
+        // Create the FileItem
+        byte[] testFieldValueBytes = createContentBytes(threshold - 1);
+        testInMemoryObject(testFieldValueBytes);
+    }
 
     /**
      * Test creation of a field for which the amount of data equals the
@@ -84,23 +99,7 @@
     public void testThreshold() throws Exception {
         // Create the FileItem
         byte[] testFieldValueBytes = createContentBytes(threshold);
-        FileItem item = createFileItem(testFieldValueBytes);
-
-        // Check state is as expected
-        assertTrue("Initial: in memory", item.isInMemory());
-        assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
-        compareBytes("Initial", item.get(), testFieldValueBytes);
-
-
-        // Serialize & Deserialize
-        FileItem newItem = (FileItem)serializeDeserialize(item);
-
-        // Test deserialized content is as expected
-        assertTrue("Check in memory", newItem.isInMemory());
-        compareBytes("Check", testFieldValueBytes, newItem.get());
-
-        // Compare FileItem's (except byte[])
-        compareFileItems(item, newItem);
+        testInMemoryObject(testFieldValueBytes);
     }
 
     /**
@@ -128,6 +127,41 @@
         // Compare FileItem's (except byte[])
         compareFileItems(item, newItem);
     }
+    
+    /**
+     * Test serialization and deserialization when repository is not null.
+     */
+    @Test
+    public void testValidRepository() throws Exception {
+        // Create the FileItem
+        byte[] testFieldValueBytes = createContentBytes(threshold);
+        File repository = new File(System.getProperty("java.io.tmpdir"));
+        testInMemoryObject(testFieldValueBytes, repository);
+    }
+    
+    /**
+     * Test deserialization fails when repository is not valid.
+     */
+    @Test(expected=IOException.class)
+    public void testInvalidRepository() throws Exception {
+        // Create the FileItem
+        byte[] testFieldValueBytes = createContentBytes(threshold);
+        File repository = new File(System.getProperty("java.io.tmpdir") + "file");
+        FileItem item = createFileItem(testFieldValueBytes, repository);
+        deserialize(serialize(item));
+    }
+    
+    /**
+     * Test deserialization fails when repository contains a null character.
+     */
+    @Test(expected=IOException.class)
+    public void testInvalidRepositoryWithNullChar() throws Exception {
+        // Create the FileItem
+        byte[] testFieldValueBytes = createContentBytes(threshold);
+        File repository = new File(System.getProperty("java.io.tmpdir") + "\0");
+        FileItem item = createFileItem(testFieldValueBytes, repository);
+        deserialize(serialize(item));
+    }
 
     /**
      * Compare FileItem's (except the byte[] content)
@@ -169,10 +203,10 @@
     }
 
     /**
-     * Create a FileItem with the specfied content bytes.
+     * Create a FileItem with the specfied content bytes and repository.
      */
-    private FileItem createFileItem(byte[] contentBytes) {
-        FileItemFactory factory = new DiskFileItemFactory(threshold, null);
+    private FileItem createFileItem(byte[] contentBytes, File repository) {
+        FileItemFactory factory = new DiskFileItemFactory(threshold, repository);
         String textFieldName = "textField";
 
         FileItem item = factory.createItem(
@@ -192,33 +226,60 @@
         return item;
 
     }
+    
+    /**
+     * Create a FileItem with the specfied content bytes.
+     */
+    private FileItem createFileItem(byte[] contentBytes) {
+        return createFileItem(contentBytes, null);
+    }
+    
+    /**
+     * Do serialization
+     */
+    private ByteArrayOutputStream serialize(Object target) throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);
+        oos.writeObject(target);
+        oos.flush();
+        oos.close();
+        return baos;
+    }
+    
+    /**
+     * Do deserialization
+     */
+    private Object deserialize(ByteArrayOutputStream baos) throws Exception {
+        Object result = null;
+        ByteArrayInputStream bais =
+                new ByteArrayInputStream(baos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        result = ois.readObject();
+        bais.close();
 
+        return result;
+    }
+    
     /**
      * Do serialization and deserialization.
      */
     private Object serializeDeserialize(Object target) {
         // Serialize the test object
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ByteArrayOutputStream baos = null;
         try {
-            ObjectOutputStream oos = new ObjectOutputStream(baos);
-            oos.writeObject(target);
-            oos.flush();
-            oos.close();
+            baos = serialize(target);
         } catch (Exception e) {
             fail("Exception during serialization: " + e);
         }
-
+        
         // Deserialize the test object
         Object result = null;
         try {
-            ByteArrayInputStream bais =
-                new ByteArrayInputStream(baos.toByteArray());
-            ObjectInputStream ois = new ObjectInputStream(bais);
-            result = ois.readObject();
-            bais.close();
+            result = deserialize(baos);
         } catch (Exception e) {
             fail("Exception during deserialization: " + e);
         }
+        
         return result;
     }