Skip to content

Commit a387ac8

Browse files
committed
Test incremental hash with huge length array added to unprocessed bytes.
1 parent f40005a commit a387ac8

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

src/main/java/org/apache/commons/codec/digest/MurmurHash3.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,7 @@ public final void add(final byte[] data, final int offset, final int length) {
10681068

10691069
// Check if the unprocessed bytes and new bytes can fill a block of 4.
10701070
// Make this overflow safe in the event that length is Integer.MAX_VALUE.
1071+
// Equivalent to: (unprocessedLength + length < BLOCK_SIZE)
10711072
if (unprocessedLength + length - BLOCK_SIZE < 0) {
10721073
// Not enough so add to the unprocessed bytes
10731074
System.arraycopy(data, offset, unprocessed, unprocessedLength, length);

src/test/java/org/apache/commons/codec/digest/MurmurHash3Test.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.commons.codec.digest;
1919

2020
import org.junit.Assert;
21+
import org.junit.Assume;
2122

2223
import java.nio.ByteBuffer;
2324
import java.util.Arrays;
@@ -890,4 +891,37 @@ private static int[] createRandomBlocks(final int maxLength) {
890891
}
891892
return Arrays.copyOf(blocks, count);
892893
}
894+
895+
/**
896+
* This test hits an edge case where a very large number of bytes is added to the incremental
897+
* hash. The data is constructed so that an integer counter of unprocessed bytes will
898+
* overflow. If this is not handled correctly then the code throws an exception when it
899+
* copies more data into the unprocessed bytes array.
900+
*/
901+
@Test
902+
public void testIncrementalHashWithUnprocessedBytesAndHugeLengthArray() {
903+
// Assert the test precondition that a large array added to unprocessed bytes
904+
// will overflow an integer counter. We use the smallest hugeLength possible
905+
// as some VMs cannot allocate maximum length arrays.
906+
final int unprocessedSize = 3;
907+
final int hugeLength = Integer.MAX_VALUE - 2;
908+
Assert.assertTrue("This should overflow to negative", unprocessedSize + hugeLength < 4);
909+
910+
// Check the test can be run
911+
byte[] bytes = null;
912+
try {
913+
bytes = new byte[hugeLength];
914+
} catch (OutOfMemoryError ignore) {
915+
// Some VMs cannot allocate an array this large.
916+
// Some test environments may not have enough available memory for this.
917+
}
918+
Assume.assumeTrue("Cannot allocate array of length " + hugeLength, bytes != null);
919+
920+
final IncrementalHash32x86 inc = new IncrementalHash32x86();
921+
inc.start(0);
922+
// Add bytes that should be unprocessed
923+
inc.add(bytes, 0, unprocessedSize);
924+
// Add a huge number of bytes to overflow an integer counter of unprocessed bytes.
925+
inc.add(bytes, 0, hugeLength);
926+
}
893927
}

0 commit comments

Comments
 (0)