/* * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
byte[] nl_1 = newbyte[] {'\n'}; byte[] nl_2 = newbyte[] {'\n', '\r'}; byte[] nl_3 = newbyte[] {'\n', '\r', '\n'}; for (int i = 0; i < 10; i++) { int len = rnd.nextInt(200) + 4;
test(Base64.getMimeEncoder(len, nl_1),
Base64.getMimeDecoder(),
numRuns, numBytes);
test(Base64.getMimeEncoder(len, nl_2),
Base64.getMimeDecoder(),
numRuns, numBytes);
test(Base64.getMimeEncoder(len, nl_3),
Base64.getMimeDecoder(),
numRuns, numBytes);
}
// test mime case with < 4 length for (int len = 0; len < 4; len++) {
test(Base64.getMimeEncoder(len, nl_1),
Base64.getMimeDecoder(),
numRuns, numBytes);
// test single-non-base64 character for mime decoding
testSingleNonBase64MimeDec();
// test decoding of unpadded data
testDecodeUnpadded();
// test mime decoding with ignored character after padding
testDecodeIgnoredAfterPadding();
// given invalid args, encoder should not produce output
testEncoderKeepsSilence(Base64.getEncoder());
testEncoderKeepsSilence(Base64.getUrlEncoder());
testEncoderKeepsSilence(Base64.getMimeEncoder());
// given invalid args, decoder should not consume input
testDecoderKeepsAbstinence(Base64.getDecoder());
testDecoderKeepsAbstinence(Base64.getUrlDecoder());
testDecoderKeepsAbstinence(Base64.getMimeDecoder());
testDecode(dec, ByteBuffer.wrap(encoded), orig);
bin = ByteBuffer.allocateDirect(encoded.length);
bin.put(encoded).flip();
testDecode(dec, bin, orig);
// --------testing decode.wrap(input stream)-------- // 1) random buf length
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
InputStream is = dec.wrap(bais);
buf = newbyte[orig.length + 10]; int len = orig.length; int off = 0; while (true) { int n = rnd.nextInt(len); if (n == 0)
n = 1;
n = is.read(buf, off, n); if (n == -1) {
checkEqual(off, orig.length, "Base64 stream decoding failed"); break;
}
off += n;
len -= n; if (len == 0) break;
}
buf = Arrays.copyOf(buf, off);
checkEqual(buf, orig, "Base64 stream decoding failed!");
// 2) read one byte each
bais.reset();
is = dec.wrap(bais);
buf = newbyte[orig.length + 10];
off = 0; int b; while ((b = is.read()) != -1) {
buf[off++] = (byte)b;
}
buf = Arrays.copyOf(buf, off);
checkEqual(buf, orig, "Base64 stream decoding failed!");
// --------testing encode.wrap(output stream)--------
ByteArrayOutputStream baos = new ByteArrayOutputStream((orig.length + 2) / 3 * 4 + 10);
OutputStream os = enc.wrap(baos);
off = 0;
len = orig.length; for (int k = 0; k < 5; k++) { if (len == 0) break; int n = rnd.nextInt(len); if (n == 0)
n = 1;
os.write(orig, off, n);
off += n;
len -= n;
} if (len != 0)
os.write(orig, off, len);
os.close();
buf = baos.toByteArray();
checkEqual(buf, encoded, "Base64 stream encoding failed!");
// 2) write one byte each
baos.reset();
os = enc.wrap(baos);
off = 0; while (off < orig.length) {
os.write(orig[off++]);
}
os.close();
buf = baos.toByteArray();
checkEqual(buf, encoded, "Base64 stream encoding failed!");
Base64.Decoder[] decs = new Base64.Decoder[] {
Base64.getDecoder(),
Base64.getUrlDecoder(),
Base64.getMimeDecoder()
};
for (Base64.Decoder dec : decs) { for (int i = 0; i < data.length; i += 3) { final String srcStr = (String)data[i]; finalbyte[] srcBytes = srcStr.getBytes("ASCII"); final ByteBuffer srcBB = ByteBuffer.wrap(srcBytes); byte[] expected = ((String)data[i + 1]).getBytes("ASCII"); int pos = (Integer)data[i + 2];
// anything left after padding is "invalid"/IAE, if // not MIME. In case of MIME, non-base64 character(s) // is ignored.
checkIAE(() -> Base64.getDecoder().decode("AA==\u00D2"));
checkIAE(() -> Base64.getUrlDecoder().decode("AA==\u00D2"));
Base64.getMimeDecoder().decode("AA==\u00D2");
}
privatestaticvoid testDecodeUnpadded() throws Throwable { byte[] srcA = newbyte[] { 'Q', 'Q' }; byte[] srcAA = newbyte[] { 'Q', 'Q', 'E'};
Base64.Decoder dec = Base64.getDecoder(); byte[] ret = dec.decode(srcA); if (ret[0] != 'A') thrownew RuntimeException("Decoding unpadding input A failed");
ret = dec.decode(srcAA); if (ret[0] != 'A' && ret[1] != 'A') thrownew RuntimeException("Decoding unpadding input AA failed");
ret = newbyte[10]; if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 &&
ret[0] != 'A') thrownew RuntimeException("Decoding unpadding input A from stream failed"); if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 &&
ret[0] != 'A' && ret[1] != 'A') thrownew RuntimeException("Decoding unpadding input AA from stream failed");
}
// single-non-base64-char should be ignored for mime decoding, but // iae for basic decoding privatestaticvoid testSingleNonBase64MimeDec() throws Throwable { for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) { if (Base64.getMimeDecoder().decode(nonBase64).length != 0) { thrownew RuntimeException("non-base64 char is not ignored");
} try {
Base64.getDecoder().decode(nonBase64); thrownew RuntimeException("No IAE for single non-base64 char");
} catch (IllegalArgumentException iae) {}
}
}
privatestaticfinalvoid checkEqual(byte[] r1, byte[] r2, String msg) throws Throwable { if (!Arrays.equals(r1, r2)) {
System.out.printf(" r1[%d]=[%s]%n", r1.length, new String(r1));
System.out.printf(" r2[%d]=[%s]%n", r2.length, new String(r2)); thrownew RuntimeException(msg);
}
}
// remove line feeds, privatestaticfinalbyte[] normalize(byte[] src) { int n = 0; boolean hasUrl = false; for (int i = 0; i < src.length; i++) { if (src[i] == '\r' || src[i] == '\n')
n++; if (src[i] == '-' || src[i] == '_')
hasUrl = true;
} if (n == 0 && hasUrl == false) return src; byte[] ret = newbyte[src.length - n]; int j = 0; for (int i = 0; i < src.length; i++) { if (src[i] == '-')
ret[j++] = '+'; elseif (src[i] == '_')
ret[j++] = '/'; elseif (src[i] != '\r' && src[i] != '\n')
ret[j++] = src[i];
} return ret;
}
privatestaticvoid testEncoderKeepsSilence(Base64.Encoder enc) throws Throwable {
List<Integer> vals = new ArrayList<>(List.of(Integer.MIN_VALUE,
Integer.MIN_VALUE + 1, -1111, -2, -1, 0, 1, 2, 3, 1111,
Integer.MAX_VALUE - 1, Integer.MAX_VALUE));
vals.addAll(List.of(rnd.nextInt(), rnd.nextInt(), rnd.nextInt(),
rnd.nextInt())); byte[] buf = newbyte[] {1, 0, 91}; for (int off : vals) { for (int len : vals) { if (off >= 0 && len >= 0 && off <= buf.length - len) { // valid args, skip them continue;
} // invalid args, test them
System.out.println("testing off=" + off + ", len=" + len);
ByteArrayOutputStream baos = new ByteArrayOutputStream(100); try (OutputStream os = enc.wrap(baos)) {
os.write(buf, off, len); thrownew RuntimeException("Expected IOOBEx was not thrown");
} catch (IndexOutOfBoundsException expected) {
} if (baos.size() > 0) thrownew RuntimeException("No output was expected, but got "
+ baos.size() + " bytes");
}
}
}
privatestaticvoid testDecoderKeepsAbstinence(Base64.Decoder dec) throws Throwable {
List<Integer> vals = new ArrayList<>(List.of(Integer.MIN_VALUE,
Integer.MIN_VALUE + 1, -1111, -2, -1, 0, 1, 2, 3, 1111,
Integer.MAX_VALUE - 1, Integer.MAX_VALUE));
vals.addAll(List.of(rnd.nextInt(), rnd.nextInt(), rnd.nextInt(),
rnd.nextInt())); byte[] buf = newbyte[3]; for (int off : vals) { for (int len : vals) { if (off >= 0 && len >= 0 && off <= buf.length - len) { // valid args, skip them continue;
} // invalid args, test them
System.out.println("testing off=" + off + ", len=" + len);
String input = "AAAAAAAAAAAAAAAAAAAAAA";
ByteArrayInputStream bais = new ByteArrayInputStream(input.getBytes("Latin1")); try (InputStream is = dec.wrap(bais)) {
is.read(buf, off, len); thrownew RuntimeException("Expected IOOBEx was not thrown");
} catch (IndexOutOfBoundsException expected) {
} if (bais.available() != input.length()) thrownew RuntimeException("No input should be consumed, "
+ "but consumed " + (input.length() - bais.available())
+ " bytes");
}
}
}
privatestaticvoid testJDK_8222187() throws Throwable { byte[] orig = "12345678".getBytes("US-ASCII"); byte[] encoded = Base64.getEncoder().encode(orig); // decode using different buffer sizes, up to a longer one than needed for (int bufferSize = 1; bufferSize <= encoded.length + 1; bufferSize++) { try (
InputStream in = Base64.getDecoder().wrap( new ByteArrayInputStream(encoded));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
) { byte[] buffer = newbyte[bufferSize]; int read; while ((read = in.read(buffer, 0, bufferSize)) >= 0) {
baos.write(buffer, 0, read);
} // compare result, output info if lengths do not match byte[] decoded = baos.toByteArray();
checkEqual(decoded, orig, "Base64 stream decoding failed!");
}
}
}
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.32Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.