diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java index 05c996f..7621560 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/HalfStoreFileReader.java @@ -148,7 +148,7 @@ public class HalfStoreFileReader extends StoreFile.Reader { return delegate.getValueString(); } - public Cell getKeyValue() { + public Cell getKeyValue() throws IOException { if (atEnd) return null; return delegate.getKeyValue(); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/AbstractHFileReader.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/AbstractHFileReader.java index 8c1e7b9..473298a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/AbstractHFileReader.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/AbstractHFileReader.java @@ -275,6 +275,9 @@ public abstract class AbstractHFileReader protected int currKeyLen; protected int currValueLen; + protected int currRowLength; + protected int currFamilyLength; + protected byte currType; protected int currMemstoreTSLen; protected long currMemstoreTS; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java index e466041..e0dc5bd 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java @@ -33,6 +33,7 @@ import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue.KVComparator; +import org.apache.hadoop.hbase.KeyValue.Type; import org.apache.hadoop.hbase.fs.HFileSystem; import org.apache.hadoop.hbase.io.FSDataInputStreamWrapper; import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder; @@ -735,12 +736,27 @@ public class HFileReaderV2 extends AbstractHFileReader { } @Override - public Cell getKeyValue() { + public Cell getKeyValue() throws IOException { if (!isSeeked()) return null; KeyValue ret = new KeyValue(blockBuffer.array(), blockBuffer.arrayOffset() + blockBuffer.position(), getCellBufSize()); + + // Do some basic sanity checks + currRowLength = ret.getRowLength(); + if (currRowLength < 0) { + throw new CorruptHFileException("Invalid rowLength " + currRowLength); + } + currFamilyLength = ret.getFamilyLength(); + if (currFamilyLength < 0) { + throw new CorruptHFileException("Invalid familyLength " + currFamilyLength); + } + currType = ret.getTypeByte(); + if (currType == Type.Minimum.getCode() || currType == Type.Maximum.getCode()) { + throw new CorruptHFileException("Invalid type " + currType); + } + if (this.reader.shouldIncludeMemstoreTS()) { ret.setSequenceId(currMemstoreTS); } @@ -973,6 +989,14 @@ public class HFileReaderV2 extends AbstractHFileReader { klen = blockBuffer.getInt(); vlen = blockBuffer.getInt(); blockBuffer.reset(); + if (klen < 0 || vlen < 0 + || klen > blockBuffer.limit() + || vlen > blockBuffer.limit()) { + throw new IllegalStateException("Invalid currKeyLen " + klen + + " or currValueLen " + vlen + ". Block offset: " + + block.getOffset() + ", block length: " + blockBuffer.limit() + + ", position: " + blockBuffer.position() + " (without header)."); + } if (this.reader.shouldIncludeMemstoreTS()) { if (this.reader.decodeMemstoreTS) { try { @@ -1196,11 +1220,25 @@ public class HFileReaderV2 extends AbstractHFileReader { } @Override - public Cell getKeyValue() { + public Cell getKeyValue() throws IOException { if (block == null) { return null; } - return seeker.getKeyValue(); + Cell kv = seeker.getKeyValue(); + // Do some basic sanity checks + currRowLength = kv.getRowLength(); + if (currRowLength < 0) { + throw new CorruptHFileException("Invalid rowLength " + currRowLength); + } + currFamilyLength = kv.getFamilyLength(); + if (currFamilyLength < 0) { + throw new CorruptHFileException("Invalid familyLength " + currFamilyLength); + } + currType = kv.getTypeByte(); + if (currType == Type.Minimum.getCode() || currType == Type.Maximum.getCode()) { + throw new CorruptHFileException("Invalid type " + currType); + } + return kv; } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileScanner.java index 1ad91e3..9c24518 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileScanner.java @@ -132,8 +132,9 @@ public interface HFileScanner { ByteBuffer getValue(); /** * @return Instance of {@link org.apache.hadoop.hbase.KeyValue}. + * @throws IOException */ - Cell getKeyValue(); + Cell getKeyValue() throws IOException; /** * Convenience method to get a copy of the key as a string - interpreting the * bytes as UTF8. You must call {@link #seekTo(byte[])} before this method.