Check checksum before decompressing data patch by Benjamin Lerer; reviewed by Branimir Lambov and Gil Tene for CASSANDRA-14284
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/34a1d5da Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/34a1d5da Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/34a1d5da Branch: refs/heads/cassandra-3.11 Commit: 34a1d5da58fb8edcad39633084541bb4162f5ede Parents: 19d26bc Author: Benjamin Lerer <b.le...@gmail.com> Authored: Tue Apr 10 09:42:52 2018 +0200 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Tue Apr 10 09:42:52 2018 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../compress/CompressedRandomAccessReader.java | 37 ++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/34a1d5da/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 0c25388..aeb3009 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.21 + * Check checksum before decompressing data (CASSANDRA-14284) * CVE-2017-5929 Security vulnerability in Logback warning in NEWS.txt (CASSANDRA-14183) 2.1.20 http://git-wip-us.apache.org/repos/asf/cassandra/blob/34a1d5da/src/java/org/apache/cassandra/io/compress/CompressedRandomAccessReader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/compress/CompressedRandomAccessReader.java b/src/java/org/apache/cassandra/io/compress/CompressedRandomAccessReader.java index 184db9c..fe90cc9 100644 --- a/src/java/org/apache/cassandra/io/compress/CompressedRandomAccessReader.java +++ b/src/java/org/apache/cassandra/io/compress/CompressedRandomAccessReader.java @@ -29,7 +29,6 @@ import org.apache.cassandra.io.sstable.CorruptSSTableException; import org.apache.cassandra.io.util.CompressedPoolingSegmentedFile; import org.apache.cassandra.io.util.PoolingSegmentedFile; import org.apache.cassandra.io.util.RandomAccessReader; -import org.apache.cassandra.utils.FBUtilities; /** * CRAR extends RAR to transparently uncompress blocks from the file into RAR.buffer. Most of the RAR @@ -107,6 +106,11 @@ public class CompressedRandomAccessReader extends RandomAccessReader // technically flip() is unnecessary since all the remaining work uses the raw array, but if that changes // in the future this will save a lot of hair-pulling compressed.flip(); + + // If the checksum is on compressed data we want to check it before uncompressing the data + if (metadata.hasPostCompressionAdlerChecksums) + checkChecksumIfNeeded(chunk, compressed.array(), chunk.length); + try { validBufferBytes = metadata.compressor().uncompress(compressed.array(), 0, chunk.length, buffer, 0); @@ -116,24 +120,9 @@ public class CompressedRandomAccessReader extends RandomAccessReader throw new CorruptBlockException(getPath(), chunk, e); } - if (metadata.parameters.getCrcCheckChance() > ThreadLocalRandom.current().nextDouble()) - { - - if (metadata.hasPostCompressionAdlerChecksums) - { - checksum.update(compressed.array(), 0, chunk.length); - } - else - { - checksum.update(buffer, 0, validBufferBytes); - } + if (!metadata.hasPostCompressionAdlerChecksums) + checkChecksumIfNeeded(chunk, buffer, validBufferBytes); - if (checksum(chunk) != (int) checksum.getValue()) - throw new CorruptBlockException(getPath(), chunk); - - // reset checksum object back to the original (blank) state - checksum.reset(); - } // buffer offset is always aligned bufferOffset = current & ~(buffer.length - 1); @@ -143,6 +132,18 @@ public class CompressedRandomAccessReader extends RandomAccessReader validBufferBytes = (int)(length() - bufferOffset); } + private void checkChecksumIfNeeded(CompressionMetadata.Chunk chunk, byte[] bytes, int length) throws IOException + { + if (metadata.parameters.getCrcCheckChance() > ThreadLocalRandom.current().nextDouble()) + { + checksum.update(bytes, 0, length); + if (checksum(chunk) != (int) checksum.getValue()) + throw new CorruptBlockException(getPath(), chunk); + // reset checksum object back to the original (blank) state + checksum.reset(); + } + } + private int checksum(CompressionMetadata.Chunk chunk) throws IOException { assert channel.position() == chunk.offset + chunk.length; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org