ACCUMULO-2299 Check that read field value has same length as expected Signed-off-by: Mike Drob <md...@cloudera.com>
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/b9303219 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/b9303219 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/b9303219 Branch: refs/heads/1.6.0-SNAPSHOT Commit: b93032190b4cc1bd00c7c0faf121899464c80919 Parents: 19e6b10 Author: Vikram Srivastava <vikr...@cloudera.com> Authored: Sun Feb 2 21:04:04 2014 -0800 Committer: Mike Drob <md...@cloudera.com> Committed: Fri Feb 7 18:35:22 2014 -0500 ---------------------------------------------------------------------- .../core/iterators/user/WholeRowIterator.java | 55 +++++++++----------- .../iterators/user/WholeRowIteratorTest.java | 24 +++++++-- 2 files changed, 44 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/b9303219/core/src/main/java/org/apache/accumulo/core/iterators/user/WholeRowIterator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/iterators/user/WholeRowIterator.java b/core/src/main/java/org/apache/accumulo/core/iterators/user/WholeRowIterator.java index e594b0c..525f27c 100644 --- a/core/src/main/java/org/apache/accumulo/core/iterators/user/WholeRowIterator.java +++ b/core/src/main/java/org/apache/accumulo/core/iterators/user/WholeRowIterator.java @@ -66,7 +66,25 @@ public class WholeRowIterator implements SortedKeyValueIterator<Key,Value> { WholeRowIterator(SortedKeyValueIterator<Key,Value> source) { this.sourceIter = source; } - + + /** + * Returns the byte array containing the field of row key from the given DataInputStream din. + * Assumes that din first has the length of the field, followed by the field itself. + */ + private static byte[] readField(DataInputStream din) throws IOException { + int len = din.readInt(); + byte[] b = new byte[len]; + int readLen = din.read(b); + // Check if expected length is not same as read length. + // We ignore the zero length case because DataInputStream.read can return -1 + // if zero length was expected and end of stream has been reached. + if (len > 0 && len != readLen) { + throw new IOException(String.format("Expected to read %d bytes but read %d", + len, readLen)); + } + return b; + } + // decode a bunch of key value pairs that have been encoded into a single value public static final SortedMap<Key,Value> decodeRow(Key rowKey, Value rowValue) throws IOException { SortedMap<Key,Value> map = new TreeMap<Key,Value>(); @@ -74,36 +92,11 @@ public class WholeRowIterator implements SortedKeyValueIterator<Key,Value> { DataInputStream din = new DataInputStream(in); int numKeys = din.readInt(); for (int i = 0; i < numKeys; i++) { - byte[] cf; - byte[] cq; - byte[] cv; - byte[] valBytes; - // read the col fam - { - int len = din.readInt(); - cf = new byte[len]; - din.read(cf); - } - // read the col qual - { - int len = din.readInt(); - cq = new byte[len]; - din.read(cq); - } - // read the col visibility - { - int len = din.readInt(); - cv = new byte[len]; - din.read(cv); - } - // read the timestamp - long timestamp = din.readLong(); - // read the value - { - int len = din.readInt(); - valBytes = new byte[len]; - din.read(valBytes); - } + byte[] cf = readField(din); // read the col fam + byte[] cq = readField(din); // read the col qual + byte[] cv = readField(din); // read the col visibility + long timestamp = din.readLong(); // read the timestamp + byte[] valBytes = readField(din); // read the value map.put(new Key(rowKey.getRowData().toArray(), cf, cq, cv, timestamp, false, false), new Value(valBytes, false)); } return map; http://git-wip-us.apache.org/repos/asf/accumulo/blob/b9303219/core/src/test/java/org/apache/accumulo/core/iterators/user/WholeRowIteratorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/iterators/user/WholeRowIteratorTest.java b/core/src/test/java/org/apache/accumulo/core/iterators/user/WholeRowIteratorTest.java index 2b86bb1..8ad97a9 100644 --- a/core/src/test/java/org/apache/accumulo/core/iterators/user/WholeRowIteratorTest.java +++ b/core/src/test/java/org/apache/accumulo/core/iterators/user/WholeRowIteratorTest.java @@ -16,8 +16,11 @@ */ package org.apache.accumulo.core.iterators.user; +import static org.junit.Assert.*; + import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -25,8 +28,6 @@ import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; -import junit.framework.TestCase; - import org.apache.accumulo.core.data.ByteSequence; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Range; @@ -35,9 +36,22 @@ import org.apache.accumulo.core.iterators.SortedKeyValueIterator; import org.apache.accumulo.core.iterators.SortedMapIterator; import org.apache.accumulo.core.iterators.system.MultiIterator; import org.apache.hadoop.io.Text; +import org.junit.Test; -public class WholeRowIteratorTest extends TestCase { - +import com.google.common.collect.ImmutableList; + +public class WholeRowIteratorTest { + + @Test(expected=IOException.class) + public void testBadDecodeRow() throws IOException { + Key k = new Key(new Text("r1"), new Text("cf1234567890")); + Value v = new Value("v1".getBytes()); + Value encoded = WholeRowIterator.encodeRow(ImmutableList.of(k), ImmutableList.of(v)); + encoded.set(Arrays.copyOfRange(encoded.get(), 0, 10)); // truncate to 10 bytes only + WholeRowIterator.decodeRow(k, encoded); + } + + @Test public void testEmptyStuff() throws IOException { SortedMap<Key,Value> map = new TreeMap<Key,Value>(); SortedMap<Key,Value> map2 = new TreeMap<Key,Value>(); @@ -108,6 +122,7 @@ public class WholeRowIteratorTest extends TestCase { map.put(new Key(new Text(row), new Text(cf), new Text(cq), new Text(cv), ts), new Value(val.getBytes())); } + @Test public void testContinue() throws Exception { SortedMap<Key,Value> map1 = new TreeMap<Key,Value>(); pkv(map1, "row1", "cf1", "cq1", "cv1", 5, "foo"); @@ -149,6 +164,7 @@ public class WholeRowIteratorTest extends TestCase { } + @Test public void testBug1() throws Exception { SortedMap<Key,Value> map1 = new TreeMap<Key,Value>(); pkv(map1, "row1", "cf1", "cq1", "cv1", 5, "foo");