Skip to content
This repository has been archived by the owner on Oct 30, 2023. It is now read-only.

Commit

Permalink
GIRAPH-1075: UnsafeByteArrayOutputStream silently writes long UTFs in…
Browse files Browse the repository at this point in the history
…correctly

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
  • Loading branch information
Maja Kabiljo committed Jun 20, 2016
1 parent 916763e commit b5a63d8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
Expand Up @@ -19,6 +19,7 @@

import java.io.IOException;
import java.io.OutputStream;
import java.io.UTFDataFormatException;
import java.lang.reflect.Field;
import java.util.Arrays;

Expand Down Expand Up @@ -289,6 +290,10 @@ public void writeUTF(String s) throws IOException {
}
}

if (utflen > 65535)
throw new UTFDataFormatException(
"encoded string too long: " + utflen + " bytes");

ensureSize(utflen + SIZE_OF_SHORT);
writeShort(utflen);

Expand Down
Expand Up @@ -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;

Expand Down Expand Up @@ -70,21 +72,42 @@ public void testWriteChars() throws IOException {

@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();
}
}

0 comments on commit b5a63d8

Please sign in to comment.