You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2020/05/09 11:55:39 UTC
[commons-codec] branch master updated: CODEC-289: Add strict
decoding to BaseNCodecInput/OutputStream
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
The following commit(s) were added to refs/heads/master by this push:
new a6b2f13 CODEC-289: Add strict decoding to BaseNCodecInput/OutputStream
a6b2f13 is described below
commit a6b2f1329beec2cd9abb86dc2ea80300e9ccb77b
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Wed May 6 22:48:12 2020 +0100
CODEC-289: Add strict decoding to BaseNCodecInput/OutputStream
---
src/changes/changes.xml | 1 +
.../codec/binary/BaseNCodecInputStream.java | 34 ++++++++++++++++++++++
.../codec/binary/BaseNCodecOutputStream.java | 34 ++++++++++++++++++++++
.../codec/binary/Base32InputStreamTest.java | 28 ++++++++++++++++++
.../codec/binary/Base32OutputStreamTest.java | 33 +++++++++++++++++++++
.../apache/commons/codec/binary/Base32Test.java | 6 +++-
.../codec/binary/Base64InputStreamTest.java | 28 ++++++++++++++++++
.../codec/binary/Base64OutputStreamTest.java | 33 +++++++++++++++++++++
.../apache/commons/codec/binary/Base64Test.java | 6 +++-
9 files changed, 201 insertions(+), 2 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f5996a3..5fc223b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -45,6 +45,7 @@ The <action> type attribute can be add,update,fix,remove.
<release version="1.15" date="YYYY-MM-DD" description="Feature and fix release.">
<action issue="CODEC-264" dev="aherbert" due-to="Andy Seaborne" type="fix">MurmurHash3: Ensure hash128 maintains the sign extension bug.</action>
<action issue="CODEC-280" dev="aherbert" type="update">Base32/Base64/BCodec: Added strict decoding property to control handling of trailing bits. Default lenient mode discards them without error. Strict mode raise an exception.</action>
+ <action issue="CODEC-289" dev="aherbert" type="update">Base32/Base64 Input/OutputStream: Added strict decoding property to control handling of trailing bits. Default lenient mode discards them without error. Strict mode raise an exception.</action>
</release>
<release version="1.14" date="2019-12-30" description="Feature and fix release.">
diff --git a/src/main/java/org/apache/commons/codec/binary/BaseNCodecInputStream.java b/src/main/java/org/apache/commons/codec/binary/BaseNCodecInputStream.java
index 58f21fe..c183c43 100644
--- a/src/main/java/org/apache/commons/codec/binary/BaseNCodecInputStream.java
+++ b/src/main/java/org/apache/commons/codec/binary/BaseNCodecInputStream.java
@@ -48,6 +48,40 @@ public class BaseNCodecInputStream extends FilterInputStream {
}
/**
+ * Sets the decoding behavior when the input bytes contain leftover trailing bits that
+ * cannot be created by a valid encoding. This setting is transferred to the instance
+ * of {@link BaseNCodec} used to perform decoding.
+ *
+ * <p>The default is false for lenient encoding. Decoding will compose trailing bits
+ * into 8-bit bytes and discard the remainder.
+ *
+ * <p>Set to true to enable strict decoding. Decoding will raise an
+ * {@link IllegalArgumentException} if trailing bits are not part of a valid encoding.
+ *
+ * @param strictDecoding Set to true to enable strict decoding; otherwise use lenient decoding.
+ * @see BaseNCodec#setStrictDecoding(boolean)
+ * @since 1.15
+ */
+ public void setStrictDecoding(boolean strictDecoding) {
+ baseNCodec.setStrictDecoding(strictDecoding);
+ }
+
+ /**
+ * Returns true if decoding behavior is strict. Decoding will raise an
+ * {@link IllegalArgumentException} if trailing bits are not part of a valid encoding.
+ *
+ * <p>The default is false for lenient encoding. Decoding will compose trailing bits
+ * into 8-bit bytes and discard the remainder.
+ *
+ * @return true if using strict decoding
+ * @see #setStrictDecoding(boolean)
+ * @since 1.15
+ */
+ public boolean isStrictDecoding() {
+ return baseNCodec.isStrictDecoding();
+ }
+
+ /**
* {@inheritDoc}
*
* @return {@code 0} if the {@link InputStream} has reached {@code EOF},
diff --git a/src/main/java/org/apache/commons/codec/binary/BaseNCodecOutputStream.java b/src/main/java/org/apache/commons/codec/binary/BaseNCodecOutputStream.java
index e6580d9..71b2a13 100644
--- a/src/main/java/org/apache/commons/codec/binary/BaseNCodecOutputStream.java
+++ b/src/main/java/org/apache/commons/codec/binary/BaseNCodecOutputStream.java
@@ -61,6 +61,40 @@ public class BaseNCodecOutputStream extends FilterOutputStream {
}
/**
+ * Sets the decoding behavior when the input bytes contain leftover trailing bits that
+ * cannot be created by a valid encoding. This setting is transferred to the instance
+ * of {@link BaseNCodec} used to perform decoding.
+ *
+ * <p>The default is false for lenient encoding. Decoding will compose trailing bits
+ * into 8-bit bytes and discard the remainder.
+ *
+ * <p>Set to true to enable strict decoding. Decoding will raise an
+ * {@link IllegalArgumentException} if trailing bits are not part of a valid encoding.
+ *
+ * @param strictDecoding Set to true to enable strict decoding; otherwise use lenient decoding.
+ * @see BaseNCodec#setStrictDecoding(boolean)
+ * @since 1.15
+ */
+ public void setStrictDecoding(boolean strictDecoding) {
+ baseNCodec.setStrictDecoding(strictDecoding);
+ }
+
+ /**
+ * Returns true if decoding behavior is strict. Decoding will raise an
+ * {@link IllegalArgumentException} if trailing bits are not part of a valid encoding.
+ *
+ * <p>The default is false for lenient encoding. Decoding will compose trailing bits
+ * into 8-bit bytes and discard the remainder.
+ *
+ * @return true if using strict decoding
+ * @see #setStrictDecoding(boolean)
+ * @since 1.15
+ */
+ public boolean isStrictDecoding() {
+ return baseNCodec.isStrictDecoding();
+ }
+
+ /**
* Writes the specified {@code byte} to this output stream.
*
* @param i
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
index e033741..85bcbb3 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
@@ -557,4 +557,32 @@ public class Base32InputStreamTest {
b32stream.skip(-10);
}
}
+
+ /**
+ * Test strict decoding.
+ *
+ * @throws Exception
+ * for some failure scenarios.
+ */
+ @Test
+ public void testStrictDecoding() throws Exception {
+ for (final String s : Base32Test.BASE32_IMPOSSIBLE_CASES) {
+ final byte[] encoded = StringUtils.getBytesUtf8(s);
+ Base32InputStream in = new Base32InputStream(new ByteArrayInputStream(encoded), false);
+ // Default is lenient decoding; it should not throw
+ assertFalse(in.isStrictDecoding());
+ Base32TestData.streamToBytes(in);
+
+ // Strict decoding should throw
+ in = new Base32InputStream(new ByteArrayInputStream(encoded), false);
+ in.setStrictDecoding(true);
+ assertTrue(in.isStrictDecoding());
+ try {
+ Base32TestData.streamToBytes(in);
+ fail();
+ } catch (final IllegalArgumentException ex) {
+ // expected
+ }
+ }
+ }
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
index 4486289..2cb09e0 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
@@ -17,6 +17,7 @@
package org.apache.commons.codec.binary;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -333,4 +334,36 @@ public class Base32OutputStreamTest {
}
}
+ /**
+ * Test strict decoding.
+ *
+ * @throws Exception
+ * for some failure scenarios.
+ */
+ @Test
+ public void testStrictDecoding() throws Exception {
+ for (final String s : Base32Test.BASE32_IMPOSSIBLE_CASES) {
+ final byte[] encoded = StringUtils.getBytesUtf8(s);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ Base32OutputStream out = new Base32OutputStream(bout, false);
+ // Default is lenient decoding; it should not throw
+ assertFalse(out.isStrictDecoding());
+ out.write(encoded);
+ out.close();
+ assertTrue(bout.size() > 0);
+
+ // Strict decoding should throw
+ bout = new ByteArrayOutputStream();
+ out = new Base32OutputStream(bout, false);
+ out.setStrictDecoding(true);
+ assertTrue(out.isStrictDecoding());
+ try {
+ out.write(encoded);
+ out.close();
+ fail();
+ } catch (final IllegalArgumentException ex) {
+ // expected
+ }
+ }
+ }
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32Test.java b/src/test/java/org/apache/commons/codec/binary/Base32Test.java
index 51d528e..7033e91 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32Test.java
@@ -48,7 +48,11 @@ public class Base32Test {
{"foobar" ,"MZXW6YTBOI======"},
};
- private static final String[] BASE32_IMPOSSIBLE_CASES = {
+ /**
+ * Example test cases with valid characters but impossible combinations of
+ * trailing characters (i.e. cannot be created during encoding).
+ */
+ static final String[] BASE32_IMPOSSIBLE_CASES = {
"MC======",
"MZXE====",
"MZXWB===",
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
index 60dd122..2b1f5cf 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
@@ -570,4 +570,32 @@ public class Base64InputStreamTest {
b64stream.skip(-10);
}
}
+
+ /**
+ * Test strict decoding.
+ *
+ * @throws Exception
+ * for some failure scenarios.
+ */
+ @Test
+ public void testStrictDecoding() throws Exception {
+ for (final String s : Base64Test.BASE64_IMPOSSIBLE_CASES) {
+ final byte[] encoded = StringUtils.getBytesUtf8(s);
+ Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(encoded), false);
+ // Default is lenient decoding; it should not throw
+ assertFalse(in.isStrictDecoding());
+ Base64TestData.streamToBytes(in);
+
+ // Strict decoding should throw
+ in = new Base64InputStream(new ByteArrayInputStream(encoded), false);
+ in.setStrictDecoding(true);
+ assertTrue(in.isStrictDecoding());
+ try {
+ Base64TestData.streamToBytes(in);
+ fail();
+ } catch (final IllegalArgumentException ex) {
+ // expected
+ }
+ }
+ }
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
index 25ff22f..b644363 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
@@ -18,6 +18,7 @@
package org.apache.commons.codec.binary;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -341,4 +342,36 @@ public class Base64OutputStreamTest {
}
}
+ /**
+ * Test strict decoding.
+ *
+ * @throws Exception
+ * for some failure scenarios.
+ */
+ @Test
+ public void testStrictDecoding() throws Exception {
+ for (final String s : Base64Test.BASE64_IMPOSSIBLE_CASES) {
+ final byte[] encoded = StringUtils.getBytesUtf8(s);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ Base64OutputStream out = new Base64OutputStream(bout, false);
+ // Default is lenient decoding; it should not throw
+ assertFalse(out.isStrictDecoding());
+ out.write(encoded);
+ out.close();
+ assertTrue(bout.size() > 0);
+
+ // Strict decoding should throw
+ bout = new ByteArrayOutputStream();
+ out = new Base64OutputStream(bout, false);
+ out.setStrictDecoding(true);
+ assertTrue(out.isStrictDecoding());
+ try {
+ out.write(encoded);
+ out.close();
+ fail();
+ } catch (final IllegalArgumentException ex) {
+ // expected
+ }
+ }
+ }
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64Test.java b/src/test/java/org/apache/commons/codec/binary/Base64Test.java
index dcccef6..8d79f59 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64Test.java
@@ -45,7 +45,11 @@ public class Base64Test {
private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
- private static final String[] BASE64_IMPOSSIBLE_CASES = {
+ /**
+ * Example test cases with valid characters but impossible combinations of
+ * trailing characters (i.e. cannot be created during encoding).
+ */
+ static final String[] BASE64_IMPOSSIBLE_CASES = {
"ZE==",
"ZmC=",
"Zm9vYE==",