Repository: giraph
Updated Branches:
  refs/heads/trunk 916763e74 -> b5a63d816


GIRAPH-1075: UnsafeByteArrayOutputStream silently writes long UTFs incorrectly

Summary: UnsafeByteArrayOutputStream.writeUTF was copied from DataOutputStream, 
but part which checks the length was missed out. When we try to write long 
strings they serialize without an issue, but when we try to deserialize them we 
get a wrong value back and don't read the same number of bytes. Make it fail 
like DataOutputStream instead.

Test Plan: Added a test

Differential Revision: https://reviews.facebook.net/D59817


Project: http://git-wip-us.apache.org/repos/asf/giraph/repo
Commit: http://git-wip-us.apache.org/repos/asf/giraph/commit/b5a63d81
Tree: http://git-wip-us.apache.org/repos/asf/giraph/tree/b5a63d81
Diff: http://git-wip-us.apache.org/repos/asf/giraph/diff/b5a63d81

Branch: refs/heads/trunk
Commit: b5a63d8162d8756e4ae73b80ff125439a1b47613
Parents: 916763e
Author: Maja Kabiljo <[email protected]>
Authored: Fri Jun 17 12:23:09 2016 -0700
Committer: Maja Kabiljo <[email protected]>
Committed: Mon Jun 20 10:15:05 2016 -0700

----------------------------------------------------------------------
 .../utils/UnsafeByteArrayOutputStream.java      |  5 +++
 .../utils/TestUnsafeByteArrayOutputStream.java  | 37 ++++++++++++++++----
 2 files changed, 35 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/giraph/blob/b5a63d81/giraph-core/src/main/java/org/apache/giraph/utils/UnsafeByteArrayOutputStream.java
----------------------------------------------------------------------
diff --git 
a/giraph-core/src/main/java/org/apache/giraph/utils/UnsafeByteArrayOutputStream.java
 
b/giraph-core/src/main/java/org/apache/giraph/utils/UnsafeByteArrayOutputStream.java
index 8736590..3c1bbba 100644
--- 
a/giraph-core/src/main/java/org/apache/giraph/utils/UnsafeByteArrayOutputStream.java
+++ 
b/giraph-core/src/main/java/org/apache/giraph/utils/UnsafeByteArrayOutputStream.java
@@ -19,6 +19,7 @@ package org.apache.giraph.utils;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.UTFDataFormatException;
 import java.lang.reflect.Field;
 import java.util.Arrays;
 
@@ -289,6 +290,10 @@ public class UnsafeByteArrayOutputStream extends 
OutputStream
       }
     }
 
+    if (utflen > 65535)
+      throw new UTFDataFormatException(
+          "encoded string too long: " + utflen + " bytes");
+
     ensureSize(utflen + SIZE_OF_SHORT);
     writeShort(utflen);
 

http://git-wip-us.apache.org/repos/asf/giraph/blob/b5a63d81/giraph-core/src/test/java/org/apache/giraph/utils/TestUnsafeByteArrayOutputStream.java
----------------------------------------------------------------------
diff --git 
a/giraph-core/src/test/java/org/apache/giraph/utils/TestUnsafeByteArrayOutputStream.java
 
b/giraph-core/src/test/java/org/apache/giraph/utils/TestUnsafeByteArrayOutputStream.java
index 2017f1f..e821cbc 100644
--- 
a/giraph-core/src/test/java/org/apache/giraph/utils/TestUnsafeByteArrayOutputStream.java
+++ 
b/giraph-core/src/test/java/org/apache/giraph/utils/TestUnsafeByteArrayOutputStream.java
@@ -17,9 +17,11 @@
  */
 package org.apache.giraph.utils;
 
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.io.IOException;
+import java.io.UTFDataFormatException;
 
 import static org.junit.Assert.assertEquals;
 
@@ -70,21 +72,42 @@ public class TestUnsafeByteArrayOutputStream {
 
     @Test
     public void testWriteUTF() throws IOException {
-        UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream();
-        int length = os.getByteArray().length;
-
         StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < length; i++) {
+        for (int i = 0; i < 20; i++) {
             sb.append("\u06ea");
         }
 
         String s = sb.toString();
-        os.writeUTF(s);
 
-        UnsafeByteArrayInputStream is = new 
UnsafeByteArrayInputStream(os.getByteArray());
+        assertEquals(s, writeAndReadUTF(s));
+    }
 
-        assertEquals(s, is.readUTF());
+    @Test
+    public void testWriteLongUTF() throws IOException {
+        int maxLength = 65535;
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < maxLength; i++) {
+            sb.append("a");
+        }
 
+        String s = sb.toString();
+
+        assertEquals(s, writeAndReadUTF(s));
+
+        s = sb.append("a").toString();
+        try {
+            writeAndReadUTF(s);
+            throw new IllegalStateException("Exception expected");
+        } catch (Exception e) {
+            Assert.assertTrue(e instanceof UTFDataFormatException);
+        }
+    }
+
+    private String writeAndReadUTF(String s) throws IOException {
+        UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream();
+        os.writeUTF(s);
         os.close();
+        UnsafeByteArrayInputStream is = new 
UnsafeByteArrayInputStream(os.getByteArray());
+        return is.readUTF();
     }
 }

Reply via email to