diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index ac5a5d6be92..172acbeab58 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -350,62 +350,6 @@ public class Base64 { return ByteBuffer.wrap(dst); } - /** - * Encodes as many bytes as possible from the input byte buffer - * using the {@link Base64} encoding scheme, writing the resulting - * bytes to the given output byte buffer. - * - *
The buffers are read from, and written to, starting at their - * current positions. Upon return, the input and output buffers' - * positions will be advanced to reflect the bytes read and written, - * but their limits will not be modified. - * - *
The encoding operation will stop and return if either all - * remaining bytes in the input buffer have been encoded and written - * to the output buffer, or the output buffer has insufficient space - * to encode any more input bytes. The encoding operation can be - * continued, if there is more bytes in input buffer to be encoded, - * by invoking this method again with an output buffer that has more - * {@linkplain java.nio.Buffer#remaining remaining} bytes. This is - * typically done by draining any encoded bytes from the output buffer. - * The value returned from last invocation needs to be passed in as the - * third parameter {@code bytesOut} if it is to continue an unfinished - * encoding, 0 otherwise. - * - *
Recommended Usage Example - *
- * ByteBuffer src = ...;
- * ByteBuffer dst = ...;
- * Base64.Encoder enc = Base64.getMimeDecoder();
- *
- * int bytesOut = 0;
- * while (src.hasRemaining()) {
- * // clear output buffer for decoding
- * dst.clear();
- * bytesOut = enc.encode(src, dst, bytesOut);
- *
- * // read encoded bytes out of "dst"
- * dst.flip();
- * ...
- * }
- *
- *
- * @param src
- * the input byte buffer to encode
- * @param dst
- * the output byte buffer
- * @param bytesOut
- * the return value of last invocation if this is to continue
- * an unfinished encoding operation, 0 otherwise
- * @return The sum total of {@code bytesOut} and the number of bytes
- * written to the output ByteBuffer during this invocation.
- */
- public int encode(ByteBuffer src, ByteBuffer dst, int bytesOut) {
- if (src.hasArray() && dst.hasArray())
- return encodeArray(src, dst, bytesOut);
- return encodeBuffer(src, dst, bytesOut);
- }
-
/**
* Wraps an output stream for encoding byte data using the {@link Base64}
* encoding scheme.
@@ -444,160 +388,6 @@ public class Base64 {
return new Encoder(isURL, newline, linemax, false);
}
- private int encodeArray(ByteBuffer src, ByteBuffer dst, int bytesOut) {
- char[] base64 = isURL? toBase64URL : toBase64;
- byte[] sa = src.array();
- int sp = src.arrayOffset() + src.position();
- int sl = src.arrayOffset() + src.limit();
- byte[] da = dst.array();
- int dp = dst.arrayOffset() + dst.position();
- int dl = dst.arrayOffset() + dst.limit();
- int dp00 = dp;
- int dpos = 0; // dp of each line
- if (linemax > 0 && bytesOut > 0)
- dpos = bytesOut % (linemax + newline.length);
- try {
- if (dpos == linemax && sp < src.limit()) {
- if (dp + newline.length > dl)
- return dp - dp00 + bytesOut;
- for (byte b : newline){
- dst.put(dp++, b);
- }
- dpos = 0;
- }
- sl = sp + (sl - sp) / 3 * 3;
- while (sp < sl) {
- int slen = (linemax > 0) ? (linemax - dpos) / 4 * 3
- : sl - sp;
- int sl0 = Math.min(sp + slen, sl);
- for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) {
- if (dp0 + 4 > dl) {
- sp = sp0; dp = dp0;
- return dp0 - dp00 + bytesOut;
- }
- int bits = (sa[sp0++] & 0xff) << 16 |
- (sa[sp0++] & 0xff) << 8 |
- (sa[sp0++] & 0xff);
- da[dp0++] = (byte)base64[(bits >>> 18) & 0x3f];
- da[dp0++] = (byte)base64[(bits >>> 12) & 0x3f];
- da[dp0++] = (byte)base64[(bits >>> 6) & 0x3f];
- da[dp0++] = (byte)base64[bits & 0x3f];
- }
- int n = (sl0 - sp) / 3 * 4;
- dpos += n;
- dp += n;
- sp = sl0;
- if (dpos == linemax && sp < src.limit()) {
- if (dp + newline.length > dl)
- return dp - dp00 + bytesOut;
- for (byte b : newline){
- da[dp++] = b;
- }
- dpos = 0;
- }
- }
- sl = src.arrayOffset() + src.limit();
- if (sp < sl && dl >= dp + 4) { // 1 or 2 leftover bytes
- int b0 = sa[sp++] & 0xff;
- da[dp++] = (byte)base64[b0 >> 2];
- if (sp == sl) {
- da[dp++] = (byte)base64[(b0 << 4) & 0x3f];
- if (doPadding) {
- da[dp++] = '=';
- da[dp++] = '=';
- }
- } else {
- int b1 = sa[sp++] & 0xff;
- da[dp++] = (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)];
- da[dp++] = (byte)base64[(b1 << 2) & 0x3f];
- if (doPadding) {
- da[dp++] = '=';
- }
- }
- }
- return dp - dp00 + bytesOut;
- } finally {
- src.position(sp - src.arrayOffset());
- dst.position(dp - dst.arrayOffset());
- }
- }
-
- private int encodeBuffer(ByteBuffer src, ByteBuffer dst, int bytesOut) {
- char[] base64 = isURL? toBase64URL : toBase64;
- int sp = src.position();
- int sl = src.limit();
- int dp = dst.position();
- int dl = dst.limit();
- int dp00 = dp;
-
- int dpos = 0; // dp of each line
- if (linemax > 0 && bytesOut > 0)
- dpos = bytesOut % (linemax + newline.length);
- try {
- if (dpos == linemax && sp < src.limit()) {
- if (dp + newline.length > dl)
- return dp - dp00 + bytesOut;
- for (byte b : newline){
- dst.put(dp++, b);
- }
- dpos = 0;
- }
- sl = sp + (sl - sp) / 3 * 3;
- while (sp < sl) {
- int slen = (linemax > 0) ? (linemax - dpos) / 4 * 3
- : sl - sp;
- int sl0 = Math.min(sp + slen, sl);
- for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) {
- if (dp0 + 4 > dl) {
- sp = sp0; dp = dp0;
- return dp0 - dp00 + bytesOut;
- }
- int bits = (src.get(sp0++) & 0xff) << 16 |
- (src.get(sp0++) & 0xff) << 8 |
- (src.get(sp0++) & 0xff);
- dst.put(dp0++, (byte)base64[(bits >>> 18) & 0x3f]);
- dst.put(dp0++, (byte)base64[(bits >>> 12) & 0x3f]);
- dst.put(dp0++, (byte)base64[(bits >>> 6) & 0x3f]);
- dst.put(dp0++, (byte)base64[bits & 0x3f]);
- }
- int n = (sl0 - sp) / 3 * 4;
- dpos += n;
- dp += n;
- sp = sl0;
- if (dpos == linemax && sp < src.limit()) {
- if (dp + newline.length > dl)
- return dp - dp00 + bytesOut;
- for (byte b : newline){
- dst.put(dp++, b);
- }
- dpos = 0;
- }
- }
- if (sp < src.limit() && dl >= dp + 4) { // 1 or 2 leftover bytes
- int b0 = src.get(sp++) & 0xff;
- dst.put(dp++, (byte)base64[b0 >> 2]);
- if (sp == src.limit()) {
- dst.put(dp++, (byte)base64[(b0 << 4) & 0x3f]);
- if (doPadding) {
- dst.put(dp++, (byte)'=');
- dst.put(dp++, (byte)'=');
- }
- } else {
- int b1 = src.get(sp++) & 0xff;
- dst.put(dp++, (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)]);
- dst.put(dp++, (byte)base64[(b1 << 2) & 0x3f]);
- if (doPadding) {
- dst.put(dp++, (byte)'=');
- }
- }
- }
- return dp - dp00 + bytesOut;
- } finally {
- src.position(sp);
- dst.position(dp);
- }
- }
-
private int encode0(byte[] src, int off, int end, byte[] dst) {
char[] base64 = isURL ? toBase64URL : toBase64;
int sp = off;
@@ -657,20 +447,11 @@ public class Base64 {
* required. So if the final unit of the encoded byte data only has
* two or three Base64 characters (without the corresponding padding
* character(s) padded), they are decoded as if followed by padding
- * character(s).
- * - * For decoders that use the Basic and - * URL and Filename safe type base64 scheme, and - * if there is padding character present in the final unit, the - * correct number of padding character(s) must be present, otherwise - * {@code IllegalArgumentException} ({@code IOException} when reading - * from a Base64 stream) is thrown during decoding. - *
- * Decoders that use the MIME type base64 scheme - * are more lenient when decoding the padding character(s). If the - * padding character(s) is incorrectly encoded, the first padding - * character encountered is interpreted as the end of the encoded byte - * data, the decoding operation will then end and return normally. + * character(s). If there is a padding character present in the + * final unit, the correct number of padding character(s) must be + * present, otherwise {@code IllegalArgumentException} ( + * {@code IOException} when reading from a Base64 stream) is thrown + * during decoding. * *
Instances of {@link Decoder} class are safe for use by * multiple concurrent threads. @@ -810,6 +591,10 @@ public class Base64 { * output buffer's position will be zero and its limit will be the * number of resulting decoded bytes * + *
{@code IllegalArgumentException} is thrown if the input buffer + * is not in valid Base64 encoding scheme. The position of the input + * buffer will not be advanced in this case. + * * @param buffer * the ByteBuffer to decode * @@ -842,76 +627,6 @@ public class Base64 { } } - /** - * Decodes as many bytes as possible from the input byte buffer - * using the {@link Base64} encoding scheme, writing the resulting - * bytes to the given output byte buffer. - * - *
The buffers are read from, and written to, starting at their - * current positions. Upon return, the input and output buffers' - * positions will be advanced to reflect the bytes read and written, - * but their limits will not be modified. - * - *
If the input buffer is not in valid Base64 encoding scheme - * then some bytes may have been written to the output buffer - * before IllegalArgumentException is thrown. The positions of - * both input and output buffer will not be advanced in this case. - * - *
The decoding operation will end and return if all remaining - * bytes in the input buffer have been decoded and written to the - * output buffer. - * - *
The decoding operation will stop and return if the output - * buffer has insufficient space to decode any more input bytes. - * The decoding operation can be continued, if there is more bytes - * in input buffer to be decoded, by invoking this method again with - * an output buffer that has more {@linkplain java.nio.Buffer#remaining - * remaining} bytes. This is typically done by draining any decoded - * bytes from the output buffer. - * - *
Recommended Usage Example - *
- * ByteBuffer src = ...;
- * ByteBuffer dst = ...;
- * Base64.Decoder dec = Base64.getDecoder();
- *
- * while (src.hasRemaining()) {
- *
- * // prepare the output byte buffer
- * dst.clear();
- * dec.decode(src, dst);
- *
- * // read bytes from the output buffer
- * dst.flip();
- * ...
- * }
- *
- *
- * @param src
- * the input byte buffer to decode
- * @param dst
- * the output byte buffer
- *
- * @return The number of bytes written to the output byte buffer during
- * this decoding invocation
- *
- * @throws IllegalArgumentException
- * if {@code src} is not in valid Base64 scheme.
- */
- public int decode(ByteBuffer src, ByteBuffer dst) {
- int sp0 = src.position();
- int dp0 = dst.position();
- try {
- if (src.hasArray() && dst.hasArray())
- return decodeArray(src, dst);
- return decodeBuffer(src, dst);
- } catch (IllegalArgumentException iae) {
- src.position(sp0);
- dst.position(dp0);
- throw iae;
- }
- }
-
/**
* Returns an input stream for decoding {@link Base64} encoded byte stream.
*
@@ -932,150 +647,6 @@ public class Base64 {
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
}
- private int decodeArray(ByteBuffer src, ByteBuffer dst) {
- int[] base64 = isURL ? fromBase64URL : fromBase64;
- int bits = 0;
- int shiftto = 18; // pos of first byte of 4-byte atom
- byte[] sa = src.array();
- int sp = src.arrayOffset() + src.position();
- int sl = src.arrayOffset() + src.limit();
- byte[] da = dst.array();
- int dp = dst.arrayOffset() + dst.position();
- int dl = dst.arrayOffset() + dst.limit();
- int dp0 = dp;
- int mark = sp;
- try {
- while (sp < sl) {
- int b = sa[sp++] & 0xff;
- if ((b = base64[b]) < 0) {
- if (b == -2) { // padding byte
- if (!isMIME &&
- (shiftto == 6 && (sp == sl || sa[sp++] != '=') ||
- shiftto == 18)) {
- throw new IllegalArgumentException(
- "Input byte array has wrong 4-byte ending unit");
- }
- break;
- }
- if (isMIME) // skip if for rfc2045
- continue;
- else
- throw new IllegalArgumentException(
- "Illegal base64 character " +
- Integer.toString(sa[sp - 1], 16));
- }
- bits |= (b << shiftto);
- shiftto -= 6;
- if (shiftto < 0) {
- if (dl < dp + 3)
- return dp - dp0;
- da[dp++] = (byte)(bits >> 16);
- da[dp++] = (byte)(bits >> 8);
- da[dp++] = (byte)(bits);
- shiftto = 18;
- bits = 0;
- mark = sp;
- }
- }
- if (shiftto == 6) {
- if (dl - dp < 1)
- return dp - dp0;
- da[dp++] = (byte)(bits >> 16);
- } else if (shiftto == 0) {
- if (dl - dp < 2)
- return dp - dp0;
- da[dp++] = (byte)(bits >> 16);
- da[dp++] = (byte)(bits >> 8);
- } else if (shiftto == 12) {
- throw new IllegalArgumentException(
- "Last unit does not have enough valid bits");
- }
- if (sp < sl) {
- if (isMIME)
- sp = sl;
- else
- throw new IllegalArgumentException(
- "Input byte array has incorrect ending byte at " + sp);
- }
- mark = sp;
- return dp - dp0;
- } finally {
- src.position(mark);
- dst.position(dp);
- }
- }
-
- private int decodeBuffer(ByteBuffer src, ByteBuffer dst) {
- int[] base64 = isURL ? fromBase64URL : fromBase64;
- int bits = 0;
- int shiftto = 18; // pos of first byte of 4-byte atom
- int sp = src.position();
- int sl = src.limit();
- int dp = dst.position();
- int dl = dst.limit();
- int dp0 = dp;
- int mark = sp;
- try {
- while (sp < sl) {
- int b = src.get(sp++) & 0xff;
- if ((b = base64[b]) < 0) {
- if (b == -2) { // padding byte
- if (!isMIME &&
- (shiftto == 6 && (sp == sl || src.get(sp++) != '=') ||
- shiftto == 18)) {
- throw new IllegalArgumentException(
- "Input byte array has wrong 4-byte ending unit");
- }
- break;
- }
- if (isMIME) // skip if for rfc2045
- continue;
- else
- throw new IllegalArgumentException(
- "Illegal base64 character " +
- Integer.toString(src.get(sp - 1), 16));
- }
- bits |= (b << shiftto);
- shiftto -= 6;
- if (shiftto < 0) {
- if (dl < dp + 3)
- return dp - dp0;
- dst.put(dp++, (byte)(bits >> 16));
- dst.put(dp++, (byte)(bits >> 8));
- dst.put(dp++, (byte)(bits));
- shiftto = 18;
- bits = 0;
- mark = sp;
- }
- }
- if (shiftto == 6) {
- if (dl - dp < 1)
- return dp - dp0;
- dst.put(dp++, (byte)(bits >> 16));
- } else if (shiftto == 0) {
- if (dl - dp < 2)
- return dp - dp0;
- dst.put(dp++, (byte)(bits >> 16));
- dst.put(dp++, (byte)(bits >> 8));
- } else if (shiftto == 12) {
- throw new IllegalArgumentException(
- "Last unit does not have enough valid bits");
- }
- if (sp < sl) {
- if (isMIME)
- sp = sl;
- else
- throw new IllegalArgumentException(
- "Input byte array has incorrect ending byte at " + sp);
- }
- mark = sp;
- return dp - dp0;
- } finally {
- src.position(mark);
- dst.position(dp);
- }
- }
-
private int outLength(byte[] src, int sp, int sl) {
int[] base64 = isURL ? fromBase64URL : fromBase64;
int paddings = 0;
@@ -1123,14 +694,13 @@ public class Base64 {
int b = src[sp++] & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte '='
- if (!isMIME && // be lenient for rfc2045
- // = shiftto==18 unnecessary padding
- // x= shiftto==12 a dangling single x
- // x to be handled together with non-padding case
- // xx= shiftto==6&&sp==sl missing last =
- // xx=y shiftto==6 last is not =
- (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
- shiftto == 18)) {
+ // = shiftto==18 unnecessary padding
+ // x= shiftto==12 a dangling single x
+ // x to be handled together with non-padding case
+ // xx= shiftto==6&&sp==sl missing last =
+ // xx=y shiftto==6 last is not =
+ if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
+ shiftto == 18) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
@@ -1160,14 +730,15 @@ public class Base64 {
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
} else if (shiftto == 12) {
- // dangling single "x", throw exception even in lenient mode,
- // it's incorrectly encoded.
+ // dangling single "x", incorrectly encoded.
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
// anything left is invalid, if is not MIME.
- // if MIME (lenient), just ignore all leftover
- if (sp < sl && !isMIME) {
+ // if MIME, ignore all non-base64 character
+ while (sp < sl) {
+ if (isMIME && base64[src[sp++]] < 0)
+ continue;
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
@@ -1367,26 +938,16 @@ public class Base64 {
// xx=y or last is not '='
if (nextin == 18 || nextin == 12 ||
nextin == 6 && is.read() != '=') {
- if (!isMIME || nextin == 12) {
- throw new IOException("Illegal base64 ending sequence:" + nextin);
- } else if (nextin != 18) {
- // lenient mode for mime
- // (1) handle the "unnecessary padding in "xxxx ="
- // case as the eof (nextin == 18)
- // (2) decode "xx=" and "xx=y" normally
- b[off++] = (byte)(bits >> (16));
- len--;
- }
- } else {
- b[off++] = (byte)(bits >> (16));
- len--;
- if (nextin == 0) { // only one padding byte
- if (len == 0) { // no enough output space
- bits >>= 8; // shift to lowest byte
- nextout = 0;
- } else {
- b[off++] = (byte) (bits >> 8);
- }
+ throw new IOException("Illegal base64 ending sequence:" + nextin);
+ }
+ b[off++] = (byte)(bits >> (16));
+ len--;
+ if (nextin == 0) { // only one padding byte
+ if (len == 0) { // no enough output space
+ bits >>= 8; // shift to lowest byte
+ nextout = 0;
+ } else {
+ b[off++] = (byte) (bits >> 8);
}
}
eof = true;
diff --git a/jdk/test/java/util/Base64/Base64GetEncoderTest.java b/jdk/test/java/util/Base64/Base64GetEncoderTest.java
index c5658d2039e..563cb797021 100644
--- a/jdk/test/java/util/Base64/Base64GetEncoderTest.java
+++ b/jdk/test/java/util/Base64/Base64GetEncoderTest.java
@@ -51,30 +51,6 @@ public class Base64GetEncoderTest {
testWrapEncode2(encoder);
- testEncodeWithByteBuffer(encoder);
-
- }
-
- private static void testEncodeWithByteBuffer(final Base64.Encoder encoder) {
- System.err.println("\n\nEncoder.encode with ByteBuffer test ");
- final byte[] secondTestBuffer =
- "api/java_util/Base64/index.html#GetEncoderMimeCustom[noLineSeparatorInEncodedString]"
- .getBytes(US_ASCII);
- String base64EncodedString;
- ByteBuffer srcData = ByteBuffer.wrap(secondTestBuffer);
- ByteBuffer dstData = ByteBuffer.allocate(secondTestBuffer.length * 2);
-
- encoder.encode(srcData, dstData, 0);
- dstData.flip();
- if (dstData.hasArray()) {
- System.err.println("\nByteBuffer test dstData is Base64 encoding = "
- + new String(dstData.array(), US_ASCII) + "\n");
- }
-
- base64EncodedString = new String(dstData.array(), US_ASCII);
- if (base64EncodedString.contains("$$$")) {
- throw new RuntimeException("Base64 encoding contains line separator after Encoder.encode ByteBuffer ... \n");
- }
}
private static void testWrapEncode2(final Base64.Encoder encoder)
diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java
index 9f7babeeeac..afa41b3d26f 100644
--- a/jdk/test/java/util/Base64/TestBase64.java
+++ b/jdk/test/java/util/Base64/TestBase64.java
@@ -23,7 +23,7 @@
/**
* @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530 8007379 8008925
- * 8014217 8025003 8026330
+ * 8014217 8025003 8026330 8028397
* @summary tests java.util.Base64
*/
@@ -92,6 +92,9 @@ public class TestBase64 {
// illegal line separator
checkIAE(new Runnable() { public void run() { Base64.getMimeEncoder(10, new byte[]{'\r', 'N'}); }});
+ // malformed padding/ending
+ testMalformedPadding();
+
// illegal base64 character
decoded[2] = (byte)0xe0;
checkIAE(new Runnable() {
@@ -100,34 +103,15 @@ public class TestBase64 {
public void run() { Base64.getDecoder().decode(decoded, new byte[1024]); }});
checkIAE(new Runnable() { public void run() {
Base64.getDecoder().decode(ByteBuffer.wrap(decoded)); }});
- checkIAE(new Runnable() { public void run() {
- Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocate(1024)); }});
- checkIAE(new Runnable() { public void run() {
- Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocateDirect(1024)); }});
-
- // illegal ending unit
- checkIOE(new Testable() { public void test() throws IOException {
- byte[] bytes = "AA=".getBytes("ASCII");
- try (InputStream stream =
- Base64.getDecoder().wrap(new ByteArrayInputStream(bytes))) {
- while (stream.read() != -1);
- }
- }});
-
- // test return value from decode(ByteBuffer, ByteBuffer)
- testDecBufRet();
// test single-non-base64 character for mime decoding
testSingleNonBase64MimeDec();
// test decoding of unpadded data
testDecodeUnpadded();
+
// test mime decoding with ignored character after padding
testDecodeIgnoredAfterPadding();
-
- // lenient mode for ending unit
- testLenientPadding();
-
}
private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder();
@@ -202,24 +186,6 @@ public class TestBase64 {
if (encoded2 != null)
testDecode(dec, ByteBuffer.wrap(encoded2), orig);
- // -------- testing encode(Buffer, Buffer)--------
- testEncode(enc, encoded,
- ByteBuffer.wrap(orig),
- ByteBuffer.allocate(encoded.length + 10));
-
- testEncode(enc, encoded,
- ByteBuffer.wrap(orig),
- ByteBuffer.allocateDirect(encoded.length + 10));
-
- // --------testing decode(Buffer, Buffer);--------
- testDecode(dec, orig,
- ByteBuffer.wrap(encoded),
- ByteBuffer.allocate(orig.length + 10));
-
- testDecode(dec, orig,
- ByteBuffer.wrap(encoded),
- ByteBuffer.allocateDirect(orig.length + 10));
-
// --------testing decode.wrap(input stream)--------
// 1) random buf length
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
@@ -322,9 +288,7 @@ public class TestBase64 {
checkNull(new Runnable() { public void run() { enc.encode(ba_null, new byte[10]); }});
checkNull(new Runnable() { public void run() { enc.encode(new byte[10], ba_null); }});
checkNull(new Runnable() { public void run() { enc.encode(bb_null); }});
- checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }});
- checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }});
- checkNull(new Runnable() { public void run() { enc.wrap(null); }});
+ checkNull(new Runnable() { public void run() { enc.wrap((OutputStream)null); }});
}
private static void testNull(final Base64.Decoder dec) {
@@ -333,9 +297,7 @@ public class TestBase64 {
checkNull(new Runnable() { public void run() { dec.decode(ba_null, new byte[10]); }});
checkNull(new Runnable() { public void run() { dec.decode(new byte[10], ba_null); }});
checkNull(new Runnable() { public void run() { dec.decode(bb_null); }});
- checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }});
- checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }});
- checkNull(new Runnable() { public void run() { dec.wrap(null); }});
+ checkNull(new Runnable() { public void run() { dec.wrap((InputStream)null); }});
}
private static interface Testable {
@@ -412,78 +374,63 @@ public class TestBase64 {
dec.decode(encoded);
throw new RuntimeException("No IAE for non-base64 char");
} catch (IllegalArgumentException iae) {}
-
- // decode(ByteBuffer[], ByteBuffer[])
- ByteBuffer encodedBB = ByteBuffer.wrap(encoded);
- ByteBuffer decodedBB = ByteBuffer.allocate(100);
- int ret = decM.decode(encodedBB, decodedBB);
- byte[] buf = new byte[ret];
- decodedBB.flip();
- decodedBB.get(buf);
- checkEqual(buf, src[i], "Non-base64 char is not ignored");
- try {
- encodedBB.rewind();
- decodedBB.clear();
- dec.decode(encodedBB, decodedBB);
- throw new RuntimeException("No IAE for non-base64 char");
- } catch (IllegalArgumentException iae) {}
- // direct
- encodedBB.rewind();
- decodedBB = ByteBuffer.allocateDirect(100);
- ret = decM.decode(encodedBB, decodedBB);
- buf = new byte[ret];
- decodedBB.flip();
- decodedBB.get(buf);
- checkEqual(buf, src[i], "Non-base64 char is not ignored");
- try {
- encodedBB.rewind();
- decodedBB.clear();
- dec.decode(encodedBB, decodedBB);
- throw new RuntimeException("No IAE for non-base64 char");
- } catch (IllegalArgumentException iae) {}
}
}
}
- private static void testLenientPadding() throws Throwable {
- String[] data = new String[] {
- "=", "", // unnecessary padding
- "QUJD=", "ABC", //"ABC".encode() -> "QUJD"
+ private static void testMalformedPadding() throws Throwable {
+ Object[] data = new Object[] {
+ "$=#", "", 0, // illegal ending unit
+ "A", "", 0, // dangling single byte
+ "A=", "", 0,
+ "A==", "", 0,
+ "QUJDA", "ABC", 4,
+ "QUJDA=", "ABC", 4,
+ "QUJDA==", "ABC", 4,
- "QQ=", "A", // incomplete padding
- "QQ=N", "A", // incorrect padding
- "QQ=?", "A",
- "QUJDQQ=", "ABCA",
- "QUJDQQ=N", "ABCA",
- "QUJDQQ=?", "ABCA",
+ "=", "", 0, // unnecessary padding
+ "QUJD=", "ABC", 4, //"ABC".encode() -> "QUJD"
- "QUI=X", "AB", // incorrect padding
- "QUI=?", "AB", // incorrect padding
+ "AA=", "", 0, // incomplete padding
+ "QQ=", "", 0,
+ "QQ=N", "", 0, // incorrect padding
+ "QQ=?", "", 0,
+ "QUJDQQ=", "ABC", 4,
+ "QUJDQQ=N", "ABC", 4,
+ "QUJDQQ=?", "ABC", 4,
};
- Base64.Decoder dec = Base64.getMimeDecoder();
- for (int i = 0; i < data.length; i += 2) {
- byte[] src = data[i].getBytes("ASCII");
- byte[] expected = data[i + 1].getBytes("ASCII");
- // decode(byte[])
- byte[] ret = dec.decode(src);
- checkEqual(ret, expected, "lenient padding decoding failed!");
+ Base64.Decoder[] decs = new Base64.Decoder[] {
+ Base64.getDecoder(),
+ Base64.getUrlDecoder(),
+ Base64.getMimeDecoder()
+ };
- // decode(String)
- ret = dec.decode(data[i]);
- checkEqual(ret, expected, "lenient padding decoding failed!");
+ for (Base64.Decoder dec : decs) {
+ for (int i = 0; i < data.length; i += 3) {
+ final String srcStr = (String)data[i];
+ final byte[] srcBytes = srcStr.getBytes("ASCII");
+ final ByteBuffer srcBB = ByteBuffer.wrap(srcBytes);
+ byte[] expected = ((String)data[i + 1]).getBytes("ASCII");
+ int pos = (Integer)data[i + 2];
- // decode(ByteBuffer)
- ByteBuffer srcBB = ByteBuffer.wrap(src);
- ByteBuffer retBB = dec.decode(srcBB);
- checkEqual(srcBB.remaining(), 0, "lenient padding decoding failed!");
- checkEqual(Arrays.copyOf(retBB.array(), retBB.remaining()),
- expected, "lenient padding decoding failed!");
+ // decode(byte[])
+ checkIAE(new Runnable() { public void run() { dec.decode(srcBytes); }});
- // wrap.decode(byte[])
- ret = new byte[10];
- int n = dec.wrap(new ByteArrayInputStream(src)).read(ret);
- checkEqual(Arrays.copyOf(ret, n), expected, "lenient padding decoding failed!");
+ // decode(String)
+ checkIAE(new Runnable() { public void run() { dec.decode(srcStr); }});
+
+ // decode(ByteBuffer)
+ checkIAE(new Runnable() { public void run() { dec.decode(srcBB); }});
+
+ // wrap stream
+ checkIOE(new Testable() {
+ public void test() throws IOException {
+ try (InputStream is = dec.wrap(new ByteArrayInputStream(srcBytes))) {
+ while (is.read() != -1);
+ }
+ }});
+ }
}
}
@@ -520,51 +467,6 @@ public class TestBase64 {
}
}
- private static void testDecBufRet() throws Throwable {
- Random rnd = new java.util.Random();
- Base64.Encoder encoder = Base64.getEncoder();
- Base64.Decoder decoder = Base64.getDecoder();
- // src pos, len expected
- int[][] tests = { { 6, 3, 3, 3}, // xxx xxx -> yyyy yyyy
- { 6, 3, 4, 3},
- { 6, 3, 5, 3},
- { 6, 3, 6, 6},
- { 6, 11, 4, 3},
- { 6, 11, 4, 3},
- { 6, 11, 5, 3},
- { 6, 11, 6, 6},
- { 7, 3, 6, 6}, // xxx xxx x -> yyyy yyyy yy==
- { 7, 3, 7, 7},
- { 7, 11, 6, 6},
- { 7, 11, 7, 7},
- { 8, 3, 6, 6}, // xxx xxx xx -> yyyy yyyy yyy=
- { 8, 3, 7, 6},
- { 8, 3, 8, 8},
- { 8, 13, 6, 6},
- { 8, 13, 7, 6},
- { 8, 13, 8, 8},
-
- };
- ByteBuffer dstBuf = ByteBuffer.allocate(100);
- for (boolean direct : new boolean[] { false, true}) {
- for (int[] test : tests) {
- byte[] src = new byte[test[0]];
- rnd.nextBytes(src);
- ByteBuffer srcBuf = direct ? ByteBuffer.allocate(100)
- : ByteBuffer.allocateDirect(100);
- srcBuf.put(encoder.encode(src)).flip();
- dstBuf.clear().position(test[1]).limit(test[1]+ test[2]);
- int ret = decoder.decode(srcBuf, dstBuf);
- if (ret != test[3]) {
- System.out.printf(" [%6s] src=%d, pos=%d, len=%d, expected=%d, ret=%d%n",
- direct?"direct":"",
- test[0], test[1], test[2], test[3], ret);
- throw new RuntimeException("ret != expected");
- }
- }
- }
- }
-
private static final void testEncode(Base64.Encoder enc, ByteBuffer bin, byte[] expected)
throws Throwable {
@@ -587,71 +489,6 @@ public class TestBase64 {
checkEqual(buf, expected, "Base64 dec.decode(bf) failed!");
}
- private static final void testEncode(Base64.Encoder enc, byte[] expected,
- ByteBuffer ibb, ByteBuffer obb)
- throws Throwable {
- Random rnd = new Random();
- int bytesOut = enc.encode(ibb, obb, 0);
- if (ibb.hasRemaining()) {
- throw new RuntimeException(
- "Base64 enc.encode(bf, bf) failed with wrong return!");
- }
- obb.flip();
- byte[] buf = new byte[obb.remaining()];
- obb.get(buf);
- checkEqual(buf, expected, "Base64 enc.encode(bf, bf) failed!");
- ibb.rewind();
- obb.position(0);
- obb.limit(0);
- bytesOut = 0;
-
- do { // increase the "limit" incrementally & randomly
- int n = rnd.nextInt(expected.length - obb.position());
- if (n == 0)
- n = 1;
- obb.limit(obb.limit() + n);
- //obb.limit(Math.min(obb.limit() + n, expected.length));
- bytesOut = enc.encode(ibb, obb, bytesOut);
- } while (ibb.hasRemaining());
- obb.flip();
- buf = new byte[obb.remaining()];
- obb.get(buf);
- checkEqual(buf, expected, "Base64 enc.encode(bf, bf) failed!");
- }
-
- private static final void testDecode(Base64.Decoder dec, byte[] expected,
- ByteBuffer ibb, ByteBuffer obb)
- throws Throwable {
- Random rnd = new Random();
-
- dec.decode(ibb, obb);
- if (ibb.hasRemaining()) {
- throw new RuntimeException(
- "Base64 dec.decode(bf, bf) failed with un-decoded ibb!");
- }
- obb.flip();
- byte[] buf = new byte[obb.remaining()];
- obb.get(buf);
- checkEqual(buf, expected, "Base64 dec.decode(bf, bf) failed!");
-
- ibb.rewind();
- obb.position(0);
- obb.limit(0);
- do { // increase the "limit" incrementally & randomly
- int n = rnd.nextInt(expected.length - obb.position());
- if (n == 0)
- n = 1;
- obb.limit(obb.limit() + n);
- dec.decode(ibb, obb);
- } while (ibb.hasRemaining());
-
-
- obb.flip();
- buf = new byte[obb.remaining()];
- obb.get(buf);
- checkEqual(buf, expected, "Base64 dec.decode(bf, bf) failed!");
- }
-
private static final void checkEqual(int v1, int v2, String msg)
throws Throwable {
if (v1 != v2) {
diff --git a/jdk/test/java/util/Base64/TestBase64Golden.java b/jdk/test/java/util/Base64/TestBase64Golden.java
index 192f2ed2391..bcee18c0829 100644
--- a/jdk/test/java/util/Base64/TestBase64Golden.java
+++ b/jdk/test/java/util/Base64/TestBase64Golden.java
@@ -55,7 +55,6 @@ public class TestBase64Golden {
test0(Base64Type.MIME, Base64.getMimeEncoder(), Base64.getMimeDecoder(),
"plain.txt", "mimeEncode.txt");
test1();
- test2();
}
public static void test0(Base64Type type, Encoder encoder, Decoder decoder,
@@ -113,28 +112,6 @@ public class TestBase64Golden {
assertEqual(resBuf, encodedBuf);
srcBuf.rewind(); // reset for next test
- // test encode(ByteBuffer, ByteBuffer, bytesOut)
- resBuf.clear();
- len = encoder.encode(srcBuf, resBuf, 0);
- assertEqual(len, encodedArr.length);
- assertEqual(srcBuf.position(), limit);
- assertEqual(srcBuf.limit(), limit);
- assertEqual(resBuf.position(), len);
- resBuf.flip();
- assertEqual(resBuf, encodedBuf);
- srcBuf.rewind();
-
- // test encode(ByteBuffer, ByteBuffer, bytesOut)[direct]
- ByteBuffer resBuf_d = ByteBuffer.allocateDirect(encodedArr.length);
- len = encoder.encode(srcBuf, resBuf_d, 0);
- assertEqual(len, encodedArr.length);
- assertEqual(srcBuf.position(), limit);
- assertEqual(srcBuf.limit(), limit);
- assertEqual(resBuf_d.position(), len);
- resBuf_d.flip();
- assertEqual(resBuf_d, encodedBuf);
- srcBuf.rewind();
-
// test String encodeToString(byte[])
String resEncodeStr = encoder.encodeToString(srcArr);
assertEqual(resEncodeStr, encodedStr);
@@ -157,28 +134,6 @@ public class TestBase64Golden {
assertEqual(resBuf, srcBuf);
encodedBuf.rewind(); // reset for next test
- // test int decode(ByteBuffer, ByteBuffer)
- resBuf.clear();
- len = decoder.decode(encodedBuf, resBuf);
- assertEqual(len, srcArr.length);
- assertEqual(encodedBuf.position(), limit);
- assertEqual(encodedBuf.limit(), limit);
- assertEqual(resBuf.position(), len);
- resBuf.flip();
- assertEqual(resBuf, srcBuf);
- encodedBuf.rewind(); // reset for next test
-
- // test int decode(ByteBuffer, ByteBuffer)[direct]
- resBuf_d = ByteBuffer.allocateDirect(srcArr.length);
- len = decoder.decode(encodedBuf, resBuf_d);
- assertEqual(len, srcArr.length);
- assertEqual(encodedBuf.position(), limit);
- assertEqual(encodedBuf.limit(), limit);
- assertEqual(resBuf_d.position(), len);
- resBuf_d.flip();
- assertEqual(resBuf_d, srcBuf);
- encodedBuf.rewind(); // reset for next test
-
// test byte[] decode(String)
resArr = decoder.decode(encodedStr);
assertEqual(resArr, srcArr);
@@ -197,35 +152,6 @@ public class TestBase64Golden {
}
private static void test1() throws Exception {
- byte[] src = new byte[6];
- new Random().nextBytes(src);
-
- ByteBuffer srcBuf = ByteBuffer.allocate(10);
- srcBuf.position(2);
- srcBuf.mark();
- srcBuf.limit(8);
- srcBuf.put(src);
- srcBuf.reset();
-
- ByteBuffer dstBuf = ByteBuffer.allocate((src.length + 2) / 3 * 4);
- Base64.getEncoder().encode(srcBuf, dstBuf, 0);
- dstBuf.rewind();
- byte[] dst = new byte[dstBuf.limit()];
- dstBuf.get(dst);
- System.out.printf("%n src[%d]: %s%n", src.length, new String(src));
- System.out.printf("encoded[%d]: %s%n", dst.length, new String(dst));
- assertEqual(src, Base64.getDecoder().decode(dst));
-
- dstBuf = ByteBuffer.allocateDirect((src.length + 2) / 3 * 4);
- srcBuf.reset();
- Base64.getEncoder().encode(srcBuf, dstBuf, 0);
- dstBuf.rewind();
- dst = new byte[dstBuf.limit()];
- dstBuf.get(dst);
- assertEqual(src, Base64.getDecoder().decode(dst));
- }
-
- private static void test2() throws Exception {
byte[] src = new byte[] {
46, -97, -35, -44, 127, -60, -39, -4, -112, 34, -57, 47, -14, 67,
40, 18, 90, -59, 68, 112, 23, 121, -91, 94, 35, 49, 104, 17, 30,