You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ju...@apache.org on 2011/01/21 20:19:51 UTC

svn commit: r1061974 - in /commons/proper/codec/trunk/src: java/org/apache/commons/codec/binary/Base64InputStream.java test/org/apache/commons/codec/binary/Base64InputStreamTest.java test/org/apache/commons/codec/binary/Base64TestData.java

Author: julius
Date: Fri Jan 21 19:19:51 2011
New Revision: 1061974

URL: http://svn.apache.org/viewvc?rev=1061974&view=rev
Log:
Fix for CODEC-101:  java.io.InputStreamReader hates it when InputStream.read(byte[]) returns a zero.

Modified:
    commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64InputStream.java
    commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64InputStreamTest.java
    commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64TestData.java

Modified: commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64InputStream.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64InputStream.java?rev=1061974&r1=1061973&r2=1061974&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64InputStream.java (original)
+++ commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64InputStream.java Fri Jan 21 19:19:51 2011
@@ -145,21 +145,41 @@ public class Base64InputStream extends F
         } else if (len == 0) {
             return 0;
         } else {
-            if (!base64.hasData()) {
-                byte[] buf = new byte[doEncode ? 4096 : 8192];
-                int c = in.read(buf);
-                // A little optimization to avoid System.arraycopy()
-                // when possible.
-                if (c > 0 && b.length == len) {
-                    base64.setInitialBuffer(b, offset, len);
-                }
-                if (doEncode) {
-                    base64.encode(buf, 0, c);
-                } else {
-                    base64.decode(buf, 0, c);
+            int readLen = 0;
+            /*
+             Rationale for while-loop on (readLen == 0):
+             -----
+             Base64.readResults() usually returns > 0 or EOF (-1).  In the
+             rare case where it returns 0, we just keep trying.
+
+             This is essentially an undocumented contract for InputStream
+             implementors that want their code to work properly with
+             java.io.InputStreamReader, since the latter hates it when
+             InputStream.read(byte[]) returns a zero.  Unfortunately our
+             readResults() call must return 0 if a large amount of the data
+             being decoded was non-base64, so this while-loop enables proper
+             interop with InputStreamReader for that scenario.
+             -----
+             This is a fix for CODEC-101
+            */
+            while (readLen == 0) {
+                if (!base64.hasData()) {
+                    byte[] buf = new byte[doEncode ? 4096 : 8192];
+                    int c = in.read(buf);
+                    // A little optimization to avoid System.arraycopy()
+                    // when possible.
+                    if (c > 0 && b.length == len) {
+                        base64.setInitialBuffer(b, offset, len);
+                    }
+                    if (doEncode) {
+                        base64.encode(buf, 0, c);
+                    } else {
+                        base64.decode(buf, 0, c);
+                    }
                 }
+                readLen = base64.readResults(b, offset, len);
             }
-            return base64.readResults(b, offset, len);
+            return readLen;
         }
     }
 

Modified: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64InputStreamTest.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64InputStreamTest.java?rev=1061974&r1=1061973&r2=1061974&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64InputStreamTest.java (original)
+++ commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64InputStreamTest.java Fri Jan 21 19:19:51 2011
@@ -47,6 +47,24 @@ public class Base64InputStreamTest exten
     }
 
     /**
+     * Test for the CODEC-101 bug:  InputStream.read(byte[]) should never return 0
+     * because Java's builtin InputStreamReader hates that.
+     *
+     * @throws Exception for some failure scenarios.
+     */
+    public void testCodec101() throws Exception {
+        byte[] codec101 = StringUtils.getBytesUtf8(Base64TestData.CODEC_101_MULTIPLE_OF_3);
+        ByteArrayInputStream bais = new ByteArrayInputStream(codec101);
+        Base64InputStream in = new Base64InputStream(bais);
+        byte[] result = new byte[8192];
+        int c = in.read(result);
+        assertTrue("Codec101: First read successful [c=" + c + "]", c > 0);
+
+        c = in.read(result);
+        assertTrue("Codec101: Second read should report end-of-stream [c=" + c + "]", c < 0);
+    }
+
+    /**
      * Test the Base64InputStream implementation against the special NPE inducing input
      * identified in the CODEC-98 bug.
      *

Modified: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64TestData.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64TestData.java?rev=1061974&r1=1061973&r2=1061974&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64TestData.java (original)
+++ commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64TestData.java Fri Jan 21 19:19:51 2011
@@ -32,6 +32,8 @@ import java.util.Random;
  */
 public class Base64TestData {
 
+    public static final String CODEC_101_MULTIPLE_OF_3 = "123";
+
     public static final String CODEC_98_NPE
         = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM";