From 47e5e19831a363aa4d675fd23ab0d06e86809094 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Wed, 17 Sep 2014 17:58:56 -0700 Subject: [PATCH] HADOOP-11040. Return value of read(ByteBuffer buf) in CryptoInputStream is incorrect in some cases. (Yi Liu via wang) --- .../hadoop-common/CHANGES.txt | 3 +++ .../hadoop/crypto/CryptoInputStream.java | 11 ++++++++++- .../hadoop/crypto/CryptoStreamsTestBase.java | 18 ++++++++++++++---- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index d2671c30245..f2b4180a9f1 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -732,6 +732,9 @@ Release 2.6.0 - UNRELEASED HDFS-7075. hadoop-fuse-dfs fails because it cannot find JavaKeyStoreProvider$Factory (cmccabe) + HADOOP-11040. Return value of read(ByteBuffer buf) in CryptoInputStream is + incorrect in some cases. (Yi Liu via wang) + BREAKDOWN OF HDFS-6134 AND HADOOP-10150 SUBTASKS AND RELATED JIRAS HADOOP-10734. Implement high-performance secure random number sources. diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java index e8964ed6ed5..68e969737c5 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java @@ -471,7 +471,16 @@ public class CryptoInputStream extends FilterInputStream implements streamOffset += n; // Read n bytes decrypt(buf, n, pos); } - return n; + + if (n >= 0) { + return unread + n; + } else { + if (unread == 0) { + return -1; + } else { + return unread; + } + } } throw new UnsupportedOperationException("ByteBuffer read unsupported " + diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/CryptoStreamsTestBase.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/CryptoStreamsTestBase.java index f5acc73b147..86bb64d882c 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/CryptoStreamsTestBase.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/CryptoStreamsTestBase.java @@ -469,6 +469,7 @@ public abstract class CryptoStreamsTestBase { int bufPos) throws Exception { buf.position(bufPos); int n = ((ByteBufferReadable) in).read(buf); + Assert.assertEquals(bufPos + n, buf.position()); byte[] readData = new byte[n]; buf.rewind(); buf.position(bufPos); @@ -568,6 +569,7 @@ public abstract class CryptoStreamsTestBase { // Read forward len1 ByteBuffer buf = ByteBuffer.allocate(len1); int nRead = ((ByteBufferReadable) in).read(buf); + Assert.assertEquals(nRead, buf.position()); readData = new byte[nRead]; buf.rewind(); buf.get(readData); @@ -575,9 +577,10 @@ public abstract class CryptoStreamsTestBase { System.arraycopy(data, (int)pos, expectedData, 0, nRead); Assert.assertArrayEquals(readData, expectedData); - // Pos should be len1 + 2 * len2 + nRead + long lastPos = pos; + // Pos should be lastPos + nRead pos = ((Seekable) in).getPos(); - Assert.assertEquals(len1 + 2 * len2 + nRead, pos); + Assert.assertEquals(lastPos + nRead, pos); // Pos: 1/3 dataLen positionedReadCheck(in , dataLen / 3); @@ -589,13 +592,15 @@ public abstract class CryptoStreamsTestBase { System.arraycopy(data, (int)pos, expectedData, 0, len1); Assert.assertArrayEquals(readData, expectedData); - // Pos should be 2 * len1 + 2 * len2 + nRead + lastPos = pos; + // Pos should be lastPos + len1 pos = ((Seekable) in).getPos(); - Assert.assertEquals(2 * len1 + 2 * len2 + nRead, pos); + Assert.assertEquals(lastPos + len1, pos); // Read forward len1 buf = ByteBuffer.allocate(len1); nRead = ((ByteBufferReadable) in).read(buf); + Assert.assertEquals(nRead, buf.position()); readData = new byte[nRead]; buf.rewind(); buf.get(readData); @@ -603,6 +608,11 @@ public abstract class CryptoStreamsTestBase { System.arraycopy(data, (int)pos, expectedData, 0, nRead); Assert.assertArrayEquals(readData, expectedData); + lastPos = pos; + // Pos should be lastPos + nRead + pos = ((Seekable) in).getPos(); + Assert.assertEquals(lastPos + nRead, pos); + // ByteBuffer read after EOF ((Seekable) in).seek(dataLen); buf.clear();