This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit a84f53d38f93504036fed5cf3fd42f57a8637b16 Author: aherbert <aherb...@apache.org> AuthorDate: Tue Nov 26 17:03:17 2019 +0000 [CODEC-259] Hex: Only use ByteBuffer.array() if length equals remaining --- .../java/org/apache/commons/codec/binary/Hex.java | 11 ++- .../org/apache/commons/codec/binary/HexTest.java | 96 ++++++++++++++++++++-- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/apache/commons/codec/binary/Hex.java b/src/main/java/org/apache/commons/codec/binary/Hex.java index 0097f09..22fc5b7 100644 --- a/src/main/java/org/apache/commons/codec/binary/Hex.java +++ b/src/main/java/org/apache/commons/codec/binary/Hex.java @@ -249,10 +249,17 @@ public class Hex implements BinaryEncoder, BinaryDecoder { } private static byte[] toByteArray(final ByteBuffer byteBuffer) { + final int remaining = byteBuffer.remaining(); + // Use the underlying buffer if possible if (byteBuffer.hasArray()) { - return byteBuffer.array(); + final byte[] byteArray = byteBuffer.array(); + if (remaining == byteArray.length) { + //byteBuffer.position(remaining); + return byteArray; + } } - final byte[] byteArray = new byte[byteBuffer.remaining()]; + // Copy the bytes + final byte[] byteArray = new byte[remaining]; byteBuffer.get(byteArray); return byteArray; } diff --git a/src/test/java/org/apache/commons/codec/binary/HexTest.java b/src/test/java/org/apache/commons/codec/binary/HexTest.java index dd562f3..34f97a4 100644 --- a/src/test/java/org/apache/commons/codec/binary/HexTest.java +++ b/src/test/java/org/apache/commons/codec/binary/HexTest.java @@ -108,6 +108,15 @@ public class HexTest { } } + private void checkDecodeHexByteBufferOddCharacters(final ByteBuffer data) { + try { + new Hex().decode(data); + fail("An exception wasn't thrown when trying to decode an odd number of characters"); + } catch (final DecoderException e) { + // Expected exception + } + } + private void checkDecodeHexCharArrayOddCharacters(final String data) { try { Hex.decodeHex(data); @@ -235,21 +244,30 @@ public class HexTest { } @Test + public void testDecodeByteBufferAllocatedButEmpty() throws DecoderException { + final ByteBuffer bb = allocate(10); + // Effectively set remaining == 0 => empty + bb.flip(); + assertTrue(Arrays.equals(new byte[0], new Hex().decode(bb))); + } + + @Test public void testDecodeByteBufferObjectEmpty() throws DecoderException { assertTrue(Arrays.equals(new byte[0], (byte[]) new Hex().decode((Object) allocate(0)))); } @Test public void testDecodeByteBufferOddCharacters() { - final ByteBuffer buffer = allocate(1); - buffer.put((byte) 65); - buffer.rewind(); - try { - new Hex().decode(buffer); - fail("An exception wasn't thrown when trying to decode an odd number of characters for " + buffer); - } catch (final DecoderException e) { - // Expected exception - } + checkDecodeHexByteBufferOddCharacters(ByteBuffer.wrap(new byte[] { 65 })); + } + + @Test + public void testDecodeByteBufferWithLimitOddCharacters() { + final ByteBuffer buffer = allocate(10); + buffer.put(1, (byte) 65); + buffer.position(1); + buffer.limit(2); + checkDecodeHexByteBufferOddCharacters(buffer); } @Test @@ -308,6 +326,18 @@ public class HexTest { } @Test + public void testDecodeByteBufferWithLimit() throws DecoderException { + final ByteBuffer bb = StringUtils.getByteBufferUtf8("000102030405060708090a0b0c0d0e0f"); + final byte[] expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + // Test pairs of bytes + for (int i = 0; i < 15; i++) { + bb.position(i * 2); + bb.limit(i * 2 + 4); + assertEquals(new String(Arrays.copyOfRange(expected, i, i + 2)), new String(new Hex().decode(bb))); + } + } + + @Test public void testEncodeByteArrayEmpty() { assertTrue(Arrays.equals(new byte[0], new Hex().encode(new byte[0]))); } @@ -323,6 +353,14 @@ public class HexTest { } @Test + public void testEncodeByteBufferAllocatedButEmpty() { + final ByteBuffer bb = allocate(10); + // Effectively set remaining == 0 => empty + bb.flip(); + assertTrue(Arrays.equals(new byte[0], new Hex().encode(bb))); + } + + @Test public void testEncodeByteBufferObjectEmpty() throws EncoderException { assertTrue(Arrays.equals(new char[0], (char[]) new Hex().encode((Object) allocate(0)))); } @@ -447,12 +485,34 @@ public class HexTest { } @Test + public void testEncodeHex_ByteBufferWithLimit() { + final ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}); + final String expected = "000102030405060708090a0b0c0d0e0f"; + // Test pairs of bytes + for (int i = 0; i < 15; i++) { + bb.position(i); + bb.limit(i + 2); + assertEquals(expected.substring(i * 2, i * 2 + 4), new String(Hex.encodeHex(bb))); + } + } + + @Test public void testEncodeHexByteString_ByteBufferOfZeroes() { final String c = Hex.encodeHexString(allocate(36)); assertEquals("000000000000000000000000000000000000000000000000000000000000000000000000", c); } @Test + public void testEncodeHexByteString_ByteBufferOfZeroesWithLimit() { + final ByteBuffer bb = allocate(36); + bb.limit(3); + assertEquals("000000", Hex.encodeHexString(bb)); + bb.position(1); + bb.limit(3); + assertEquals("0000", Hex.encodeHexString(bb)); + } + + @Test public void testEncodeHexByteString_ByteArrayOfZeroes() { final String c = Hex.encodeHexString(new byte[36]); assertEquals("000000000000000000000000000000000000000000000000000000000000000000000000", c); @@ -479,6 +539,24 @@ public class HexTest { } @Test + public void testEncodeHexByteString_ByteBufferWithLimitBoolean_ToLowerCase() { + final ByteBuffer bb = allocate(4); + bb.put(1, (byte) 10); + bb.position(1); + bb.limit(2); + assertEquals("0a", Hex.encodeHexString(bb, true)); + } + + @Test + public void testEncodeHexByteString_ByteBufferWithLimitBoolean_ToUpperCase() { + final ByteBuffer bb = allocate(4); + bb.put(1, (byte) 10); + bb.position(1); + bb.limit(2); + assertEquals("0A", Hex.encodeHexString(bb, false)); + } + + @Test public void testEncodeStringEmpty() throws EncoderException { assertTrue(Arrays.equals(new char[0], (char[]) new Hex().encode(""))); }