Skip to content

Commit 95fd310

Browse files
authored
FIxing WritableBytesConverter to not overwrite bytes with wrong value (#2075)
1 parent b9908c8 commit 95fd310

File tree

3 files changed

+97
-8
lines changed

3 files changed

+97
-8
lines changed

mr/src/main/java/org/elasticsearch/hadoop/mr/SafeWritableConverter.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,26 @@ public SafeWritableConverter() {
3131
Text.class.getName(); // force class to be loaded
3232
}
3333

34-
public void invoke(Object from, BytesArray to) {
34+
/**
35+
* If from is a Text or BytesWritable, the value is written to the to field, and true is returned. Otherwise does not write to
36+
* the to field and returns false.
37+
* @param from The object to copy bytes from
38+
* @param to The BytesArray to copy bytes to
39+
* @return true if from has been handled
40+
*/
41+
public boolean invoke(Object from, BytesArray to) {
3542
// handle common cases
3643
if (from instanceof Text) {
3744
Text t = (Text) from;
3845
to.bytes(t.getBytes(), t.getLength());
46+
return true;
3947
}
40-
if (from instanceof BytesWritable) {
48+
else if (from instanceof BytesWritable) {
4149
BytesWritable b = (BytesWritable) from;
4250
to.bytes(b.getBytes(), b.getLength());
51+
return true;
52+
} else {
53+
return false;
4354
}
4455
}
4556
}

mr/src/main/java/org/elasticsearch/hadoop/mr/WritableBytesConverter.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ public class WritableBytesConverter extends JdkBytesConverter {
3535

3636
@Override
3737
public void convert(Object from, BytesArray to) {
38-
39-
if (safeWritableConverter != null)
40-
safeWritableConverter.invoke(from, to);
41-
42-
super.convert(from, to);
38+
final boolean handled;
39+
if (safeWritableConverter != null) {
40+
handled = safeWritableConverter.invoke(from, to);
41+
} else {
42+
handled = false;
43+
}
44+
if (handled == false) {
45+
super.convert(from, to);
46+
}
4347
}
44-
}
48+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.elasticsearch.hadoop.mr;
2+
3+
import org.apache.hadoop.io.BytesWritable;
4+
import org.apache.hadoop.io.Text;
5+
import org.elasticsearch.hadoop.util.BytesArray;
6+
import org.junit.Test;
7+
8+
import java.security.SecureRandom;
9+
import java.util.concurrent.ThreadLocalRandom;
10+
11+
import static org.junit.Assert.assertArrayEquals;
12+
import static org.junit.Assert.assertEquals;
13+
14+
public class WritableBytesConverterTests {
15+
16+
@Test
17+
public void testConvertBytesWritable() throws Exception {
18+
WritableBytesConverter converter = new WritableBytesConverter();
19+
byte[] randomBytes = new byte[20];
20+
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
21+
Object input = new BytesWritable(randomBytes);
22+
BytesArray output = new BytesArray(10);
23+
converter.convert(input, output);
24+
assertEquals(randomBytes.length, output.length());
25+
assertArrayEquals(randomBytes, output.bytes());
26+
}
27+
28+
@Test
29+
public void testConvertInteger() {
30+
WritableBytesConverter converter = new WritableBytesConverter();
31+
int inputInteger = ThreadLocalRandom.current().nextInt();
32+
Object input = inputInteger;
33+
BytesArray output = new BytesArray(10);
34+
converter.convert(input, output);
35+
// Integer is not directly supported, so we expect its string value to be used:
36+
assertEquals(Integer.toString(inputInteger), output.toString());
37+
}
38+
39+
@Test
40+
public void testConvertText() {
41+
WritableBytesConverter converter = new WritableBytesConverter();
42+
Text input = new Text("This is some text");
43+
BytesArray output = new BytesArray(10);
44+
converter.convert(input, output);
45+
assertEquals(input.getLength(), output.length());
46+
assertArrayEquals(input.getBytes(), output.bytes());
47+
}
48+
49+
@Test
50+
public void testConvertByteArray() throws Exception {
51+
WritableBytesConverter converter = new WritableBytesConverter();
52+
byte[] input = new byte[20];
53+
SecureRandom.getInstanceStrong().nextBytes(input);
54+
BytesArray output = new BytesArray(10);
55+
converter.convert(input, output);
56+
assertEquals(input.length, output.length());
57+
assertArrayEquals(input, output.bytes());
58+
}
59+
60+
@Test
61+
public void testConvertBytesArray() throws Exception {
62+
WritableBytesConverter converter = new WritableBytesConverter();
63+
byte[] randomBytes = new byte[20];
64+
SecureRandom.getInstanceStrong().nextBytes(randomBytes);
65+
Object input = new BytesArray(randomBytes);
66+
BytesArray output = new BytesArray(10);
67+
converter.convert(input, output);
68+
assertEquals(randomBytes.length, output.length());
69+
byte[] usedOutputBytes = new byte[output.length()];
70+
// BytesArray::bytes can give you bytes beyond length
71+
System.arraycopy(output.bytes(), 0, usedOutputBytes, 0, output.length());
72+
assertArrayEquals(randomBytes, usedOutputBytes);
73+
}
74+
}

0 commit comments

Comments
 (0)