Skip to content

Commit a84f53d

Browse files
committed
[CODEC-259] Hex: Only use ByteBuffer.array() if length equals remaining
1 parent a3a4edd commit a84f53d

2 files changed

Lines changed: 96 additions & 11 deletions

File tree

  • src
    • main/java/org/apache/commons/codec/binary
    • test/java/org/apache/commons/codec/binary

src/main/java/org/apache/commons/codec/binary/Hex.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,17 @@ public static String encodeHexString(final ByteBuffer data, final boolean toLowe
249249
}
250250

251251
private static byte[] toByteArray(final ByteBuffer byteBuffer) {
252+
final int remaining = byteBuffer.remaining();
253+
// Use the underlying buffer if possible
252254
if (byteBuffer.hasArray()) {
253-
return byteBuffer.array();
255+
final byte[] byteArray = byteBuffer.array();
256+
if (remaining == byteArray.length) {
257+
//byteBuffer.position(remaining);
258+
return byteArray;
259+
}
254260
}
255-
final byte[] byteArray = new byte[byteBuffer.remaining()];
261+
// Copy the bytes
262+
final byte[] byteArray = new byte[remaining];
256263
byteBuffer.get(byteArray);
257264
return byteArray;
258265
}

src/test/java/org/apache/commons/codec/binary/HexTest.java

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ private void checkDecodeHexCharArrayOddCharacters(final char[] data) {
108108
}
109109
}
110110

111+
private void checkDecodeHexByteBufferOddCharacters(final ByteBuffer data) {
112+
try {
113+
new Hex().decode(data);
114+
fail("An exception wasn't thrown when trying to decode an odd number of characters");
115+
} catch (final DecoderException e) {
116+
// Expected exception
117+
}
118+
}
119+
111120
private void checkDecodeHexCharArrayOddCharacters(final String data) {
112121
try {
113122
Hex.decodeHex(data);
@@ -234,22 +243,31 @@ public void testDecodeByteBufferEmpty() throws DecoderException {
234243
assertTrue(Arrays.equals(new byte[0], new Hex().decode(allocate(0))));
235244
}
236245

246+
@Test
247+
public void testDecodeByteBufferAllocatedButEmpty() throws DecoderException {
248+
final ByteBuffer bb = allocate(10);
249+
// Effectively set remaining == 0 => empty
250+
bb.flip();
251+
assertTrue(Arrays.equals(new byte[0], new Hex().decode(bb)));
252+
}
253+
237254
@Test
238255
public void testDecodeByteBufferObjectEmpty() throws DecoderException {
239256
assertTrue(Arrays.equals(new byte[0], (byte[]) new Hex().decode((Object) allocate(0))));
240257
}
241258

242259
@Test
243260
public void testDecodeByteBufferOddCharacters() {
244-
final ByteBuffer buffer = allocate(1);
245-
buffer.put((byte) 65);
246-
buffer.rewind();
247-
try {
248-
new Hex().decode(buffer);
249-
fail("An exception wasn't thrown when trying to decode an odd number of characters for " + buffer);
250-
} catch (final DecoderException e) {
251-
// Expected exception
252-
}
261+
checkDecodeHexByteBufferOddCharacters(ByteBuffer.wrap(new byte[] { 65 }));
262+
}
263+
264+
@Test
265+
public void testDecodeByteBufferWithLimitOddCharacters() {
266+
final ByteBuffer buffer = allocate(10);
267+
buffer.put(1, (byte) 65);
268+
buffer.position(1);
269+
buffer.limit(2);
270+
checkDecodeHexByteBufferOddCharacters(buffer);
253271
}
254272

255273
@Test
@@ -307,6 +325,18 @@ public void testDecodeStringEmpty() throws DecoderException {
307325
assertTrue(Arrays.equals(new byte[0], (byte[]) new Hex().decode("")));
308326
}
309327

328+
@Test
329+
public void testDecodeByteBufferWithLimit() throws DecoderException {
330+
final ByteBuffer bb = StringUtils.getByteBufferUtf8("000102030405060708090a0b0c0d0e0f");
331+
final byte[] expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
332+
// Test pairs of bytes
333+
for (int i = 0; i < 15; i++) {
334+
bb.position(i * 2);
335+
bb.limit(i * 2 + 4);
336+
assertEquals(new String(Arrays.copyOfRange(expected, i, i + 2)), new String(new Hex().decode(bb)));
337+
}
338+
}
339+
310340
@Test
311341
public void testEncodeByteArrayEmpty() {
312342
assertTrue(Arrays.equals(new byte[0], new Hex().encode(new byte[0])));
@@ -322,6 +352,14 @@ public void testEncodeByteBufferEmpty() {
322352
assertTrue(Arrays.equals(new byte[0], new Hex().encode(allocate(0))));
323353
}
324354

355+
@Test
356+
public void testEncodeByteBufferAllocatedButEmpty() {
357+
final ByteBuffer bb = allocate(10);
358+
// Effectively set remaining == 0 => empty
359+
bb.flip();
360+
assertTrue(Arrays.equals(new byte[0], new Hex().encode(bb)));
361+
}
362+
325363
@Test
326364
public void testEncodeByteBufferObjectEmpty() throws EncoderException {
327365
assertTrue(Arrays.equals(new char[0], (char[]) new Hex().encode((Object) allocate(0))));
@@ -446,12 +484,34 @@ public void testEncodeHex_ByteBufferOfZeroes() {
446484
assertEquals("000000000000000000000000000000000000000000000000000000000000000000000000", new String(c));
447485
}
448486

487+
@Test
488+
public void testEncodeHex_ByteBufferWithLimit() {
489+
final ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
490+
final String expected = "000102030405060708090a0b0c0d0e0f";
491+
// Test pairs of bytes
492+
for (int i = 0; i < 15; i++) {
493+
bb.position(i);
494+
bb.limit(i + 2);
495+
assertEquals(expected.substring(i * 2, i * 2 + 4), new String(Hex.encodeHex(bb)));
496+
}
497+
}
498+
449499
@Test
450500
public void testEncodeHexByteString_ByteBufferOfZeroes() {
451501
final String c = Hex.encodeHexString(allocate(36));
452502
assertEquals("000000000000000000000000000000000000000000000000000000000000000000000000", c);
453503
}
454504

505+
@Test
506+
public void testEncodeHexByteString_ByteBufferOfZeroesWithLimit() {
507+
final ByteBuffer bb = allocate(36);
508+
bb.limit(3);
509+
assertEquals("000000", Hex.encodeHexString(bb));
510+
bb.position(1);
511+
bb.limit(3);
512+
assertEquals("0000", Hex.encodeHexString(bb));
513+
}
514+
455515
@Test
456516
public void testEncodeHexByteString_ByteArrayOfZeroes() {
457517
final String c = Hex.encodeHexString(new byte[36]);
@@ -478,6 +538,24 @@ public void testEncodeHexByteString_ByteBufferBoolean_ToUpperCase() {
478538
assertEquals("0A", Hex.encodeHexString(ByteBuffer.wrap(new byte[] { 10 }), false));
479539
}
480540

541+
@Test
542+
public void testEncodeHexByteString_ByteBufferWithLimitBoolean_ToLowerCase() {
543+
final ByteBuffer bb = allocate(4);
544+
bb.put(1, (byte) 10);
545+
bb.position(1);
546+
bb.limit(2);
547+
assertEquals("0a", Hex.encodeHexString(bb, true));
548+
}
549+
550+
@Test
551+
public void testEncodeHexByteString_ByteBufferWithLimitBoolean_ToUpperCase() {
552+
final ByteBuffer bb = allocate(4);
553+
bb.put(1, (byte) 10);
554+
bb.position(1);
555+
bb.limit(2);
556+
assertEquals("0A", Hex.encodeHexString(bb, false));
557+
}
558+
481559
@Test
482560
public void testEncodeStringEmpty() throws EncoderException {
483561
assertTrue(Arrays.equals(new char[0], (char[]) new Hex().encode("")));

0 commit comments

Comments
 (0)