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 97272858836aa93f28f2f675c8c1d124cf753e25
Author: Adam Retter <adam.ret...@googlemail.com>
AuthorDate: Mon Jun 1 15:10:17 2020 +0200

    Throw IllegalArgumentException for characters outside of alphabet
---
 .../org/apache/commons/codec/binary/Base16.java    | 29 ++++++++++++++++------
 .../apache/commons/codec/binary/Base16Test.java    | 26 ++++++++++---------
 2 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java 
b/src/main/java/org/apache/commons/codec/binary/Base16.java
index eb875cb..b421e23 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -151,7 +151,7 @@ public class Base16 extends BaseNCodec {
 
         // small optimisation to short-cut the rest of this method when it is 
fed byte-by-byte
         if (availableChars == 1 && availableChars == dataLen) {
-            context.ibitWorkArea = data[offset];   // store 1/2 byte for next 
invocation of decode
+            context.ibitWorkArea = decodeOctet(data[offset]) + 1;   // store 
1/2 byte for next invocation of decode, we offset by +1 as empty-value is 0
             return;
         }
 
@@ -164,29 +164,42 @@ public class Base16 extends BaseNCodec {
         int i = 0;
         if (dataLen < availableChars) {
             // we have 1/2 byte from previous invocation to decode
-            result = decodeTable[context.ibitWorkArea] << 
BITS_PER_ENCODED_BYTE;
-            result |= decodeTable[data[offset++]];
+            result = (context.ibitWorkArea - 1) << BITS_PER_ENCODED_BYTE;
+            result |= decodeOctet(data[offset++]);
             i = 2;
 
             buffer[context.pos++] = (byte)result;
 
-            // reset for next invocation!
-            context.ibitWorkArea = -1;
+            // reset to empty-value for next invocation!
+            context.ibitWorkArea = 0;
         }
 
         while (i < charsToProcess) {
-            result = decodeTable[data[offset++]] << BITS_PER_ENCODED_BYTE;
-            result |= decodeTable[data[offset++]];
+            result = decodeOctet(data[offset++]) << BITS_PER_ENCODED_BYTE;
+            result |= decodeOctet(data[offset++]);
             i += 2;
             buffer[context.pos++] = (byte)result;
         }
 
         // we have one char of a hex-pair left over
         if (i < dataLen) {
-            context.ibitWorkArea = data[i];   // store 1/2 byte for next 
invocation of decode
+            context.ibitWorkArea = decodeOctet(data[i]) + 1;   // store 1/2 
byte for next invocation of decode, we offset by +1 as empty-value is 0
         }
     }
 
+    private int decodeOctet(final byte octet) {
+        int decoded = -1;
+        if (octet >= 0 && octet < decodeTable.length) {
+            decoded = decodeTable[octet];
+        }
+
+        if (decoded == -1) {
+            throw new IllegalArgumentException("Invalid octet in encoded 
value: " + (int)octet);
+        }
+
+        return decoded;
+    }
+
     @Override
     void encode(final byte[] data, final int offset, final int length, final 
Context context) {
         if (context.eof) {
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java 
b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 989520a..72bff8a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -205,16 +205,17 @@ public class Base16Test {
 
     @Test
     public void testNonBase16Test() {
-        final byte[] bArray = { '%' };
-
-        try {
-            final Base16 b16 = new Base16();
-            final byte[] result = b16.decode(bArray);
-
-            assertEquals("The result should be empty as the test encoded 
content did "
-                    + "not contain any valid base 16 characters", 0, 
result.length);
-        } catch (final Exception e) {
-            fail("Exception was thrown when trying to decode invalid Base16 
encoded data");
+        final byte[] invalidEncodedChars = { '/', ':', '@', 'G', '%', '`', 'g' 
};
+
+        final byte[] encoded = new byte[1];
+        for (final byte invalidEncodedChar : invalidEncodedChars) {
+            try {
+                encoded[0] = invalidEncodedChar;
+                new Base16().decode(encoded);
+                fail("IllegalArgumentException should have been thrown when 
trying to decode invalid Base16 char: " + (char)invalidEncodedChar);
+            } catch (final Exception e) {
+                assertTrue(e instanceof IllegalArgumentException);
+            }
         }
     }
 
@@ -591,14 +592,15 @@ public class Base16Test {
         final byte[] data = new byte[1];
 
         final Base16 b16 = new Base16();
+        assertEquals(0, context.ibitWorkArea);
 
         data[0] = (byte) 'E';
         b16.decode(data, 0, 1, context);
-        assertEquals(69, context.ibitWorkArea);
+        assertEquals(15, context.ibitWorkArea);
 
         data[0] = (byte) 'F';
         b16.decode(data, 0, 1, context);
-        assertEquals(-1, context.ibitWorkArea);
+        assertEquals(0, context.ibitWorkArea);
 
         assertEquals(-17, context.buffer[0]);
     }

Reply via email to