Author: julius Date: Tue Jun 1 21:52:33 2010 New Revision: 950267 URL: http://svn.apache.org/viewvc?rev=950267&view=rev Log: CODEC-98 - Base64InputStream causes NullPointerException on some input - https://issues.apache.org/jira/browse/CODEC-98
Modified: commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64.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/Base64OutputStreamTest.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/Base64.java URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64.java?rev=950267&r1=950266&r2=950267&view=diff ============================================================================== --- commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64.java (original) +++ commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base64.java Tue Jun 1 21:52:33 2010 @@ -583,6 +583,10 @@ public class Base64 implements BinaryEnc // EOF (-1) and first time '=' character is encountered in stream. // This approach makes the '=' padding characters completely optional. if (eof && modulus != 0) { + if (buffer == null || buffer.length - pos < decodeSize) { + resizeBuffer(); + } + x = x << 6; switch (modulus) { case 2 : 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=950267&r1=950266&r2=950267&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 Tue Jun 1 21:52:33 2010 @@ -47,6 +47,26 @@ public class Base64InputStreamTest exten } /** + * Test the Base64InputStream implementation against the special NPE inducing input + * identified in the CODEC-98 bug. + * + * @throws Exception for some failure scenarios. + */ + public void testCodec98NPE() throws Exception { + byte[] codec98 = StringUtils.getBytesUtf8(Base64TestData.CODEC_98_NPE); + ByteArrayInputStream data = new ByteArrayInputStream(codec98); + Base64InputStream stream = new Base64InputStream(data); + + // This line causes an NPE in commons-codec-1.4.jar: + byte[] decodedBytes = Base64TestData.streamToBytes(stream, new byte[1024]); + + String decoded = StringUtils.newStringUtf8(decodedBytes); + assertEquals( + "codec-98 NPE Base64InputStream", Base64TestData.CODEC_98_NPE_DECODED, decoded + ); + } + + /** * Tests the Base64InputStream implementation against empty input. * * @throws Exception Modified: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64OutputStreamTest.java URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64OutputStreamTest.java?rev=950267&r1=950266&r2=950267&view=diff ============================================================================== --- commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64OutputStreamTest.java (original) +++ commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base64OutputStreamTest.java Tue Jun 1 21:52:33 2010 @@ -47,6 +47,29 @@ public class Base64OutputStreamTest exte } /** + * Test the Base64OutputStream implementation against the special NPE inducing input + * identified in the CODEC-98 bug. + * + * @throws Exception for some failure scenarios. + */ + public void testCodec98NPE() throws Exception { + byte[] codec98 = StringUtils.getBytesUtf8(Base64TestData.CODEC_98_NPE); + byte[] codec98_1024 = new byte[1024]; + System.arraycopy(codec98, 0, codec98_1024, 0, codec98.length); + ByteArrayOutputStream data = new ByteArrayOutputStream(1024); + Base64OutputStream stream = new Base64OutputStream(data, false); + stream.write(codec98_1024, 0, 1024); + stream.close(); + + byte[] decodedBytes = data.toByteArray(); + String decoded = StringUtils.newStringUtf8(decodedBytes); + assertEquals( + "codec-98 NPE Base64OutputStream", Base64TestData.CODEC_98_NPE_DECODED, decoded + ); + } + + + /** * Test the Base64OutputStream implementation against empty input. * * @throws Exception 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=950267&r1=950266&r2=950267&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 Tue Jun 1 21:52:33 2010 @@ -32,6 +32,13 @@ import java.util.Random; */ public class Base64TestData { + public static final String CODEC_98_NPE + = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM"; + + public static final String CODEC_98_NPE_DECODED + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123"; + + // OpenSSL doesn't include the final \n, but it would be annoying beyond belief // to further parameterize commons-codec to support this pointless variation. final static String ENCODED_64_CHARS_PER_LINE @@ -133,7 +140,10 @@ public class Base64TestData { static byte[] streamToBytes(final InputStream in) throws IOException { // new byte[7] is obviously quite slow, but helps exercise the code. - byte[] buf = new byte[7]; + return streamToBytes(in, new byte[7]); + } + + static byte[] streamToBytes(final InputStream in, byte[] buf) throws IOException { try { int[] status = fill(buf, 0, in); int size = status[SIZE_KEY];