/* * Copyright (c) 2008, 2018, 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.
*/
/* * @test * @bug 6233345 6381699 6381702 6381705 6381706 * @summary Encode many char sequences in many ways * @library /test/lib * @build jdk.test.lib.RandomFactory * @run main/timeout=1200 FindEncoderBugs * @author Martin Buchholz * @key randomness
*/
static String string(byte[] a) { final StringBuilder sb = new StringBuilder(); for (byte b : a) { if (sb.length() != 0) sb.append(' ');
sb.append(String.format("%02x", b & 0xff));
} return sb.toString();
}
static String string(char[] a) { final StringBuilder sb = new StringBuilder(); for (char c : a) { if (sb.length() != 0) sb.append(' ');
sb.append(String.format("\\u%04x", (int) c));
} return sb.toString();
}
staticclass Reporter { // Some machinery to make sure only a small number of errors // that are "too similar" are reported. staticclass Counts extends HashMap<String, Long> { privatestaticfinallong serialVersionUID = -1; long inc(String signature) { Long count = get(signature); if (count == null) count = 0L;
put(signature, count+1); return count+1;
}
}
final Counts failureCounts = new Counts(); finalstaticlong maxFailures = 2;
staticboolean bug(String format, Object... args) { return reporter.bug(format, args);
}
staticboolean hasBom(byte[] a) { switch (a.length) { case 2: case 4: int sum = 0; for (byte x : a)
sum += x; return sum == (byte) 0xfe + (byte) 0xff; default: returnfalse;
}
}
void testSurrogates() { int failures = 0; for (int i = 0; i < 10; i++) {
Result r = test(newchar[] { randomHighSurrogate() }); if (r == null) break; if (! (r.cr.isUnderflow() &&
r.ipos == 0))
bug("Lone high surrogate not UNDERFLOW: %s %s",
cs, r);
} for (int i = 0; i < 10; i++) {
Result r = test(newchar[] { randomLowSurrogate() }); if (r == null) break; if (! (r.cr.isMalformed() && r.cr.length() == 1))
bug("Lone low surrogate not MALFORMED[1]: %s %s",
cs, r);
} char[] chars = newchar[2]; for (int i = 0; i < 10; i++) {
chars[0] = randomLowSurrogate(); // Always illegal
chars[1] = randomChar();
Result r = test(chars); if (r == null) break; if (! (r.cr.isMalformed() &&
r.cr.length() == 1 &&
(r.ipos == 0 || (hasBom && hasBom(r.oa))))) { if (failures++ > 5) return;
bug("Unpaired low surrogate not MALFORMED[1]: %s %s",
cs, r);
}
} for (int i = 0; i < 10; i++) {
chars[0] = randomHighSurrogate(); do {
chars[1] = randomChar();
} while (Character.isLowSurrogate(chars[1]));
Result r = test(chars); if (r == null) break; if (! (r.cr.isMalformed() &&
r.cr.length() == 1 &&
(r.ipos == 0 || (hasBom && hasBom(r.oa))))) { if (failures++ > 5) return;
bug("Unpaired high surrogate not MALFORMED[1]: %s %s",
cs, r);
}
} for (int i = 0; i < 1000; i++) {
chars[0] = randomHighSurrogate();
chars[1] = randomLowSurrogate();
Result r = test(chars); if (r == null) break; if (! ((r.cr.isUnmappable() &&
r.cr.length() == 2 &&
r.oa.length == 0)
||
(r.cr.isUnderflow() &&
r.oa.length > 0 &&
r.ipos == 2))) { if (failures++ > 5) return;
bug("Legal supplementary character bug: %s %s",
cs, r);
}
}
}
// dib.clear(); dib.put(chars); dib.flip(); // rib.position(0); // rob.clear(); rob.limit(lim); // for (CharBuffer ib : new CharBuffer[] { rib, dib }) { // Result r = recode(ib, rob); // if (! (r.cr.isMalformed() && // r.cr.length() == 1 && // (rob.position() == 0 || hasBom(rob)))) { // if (failures++ > 5) return; // bug("Unpaired surrogate not malformed: %s %s", // cs, r); // } // } // //} // for (int i = 0; i < 10000; i++) { // chars[0] = randomHighSurrogate(); // chars[1] = randomLowSurrogate(); // dib.clear(); dib.put(chars); dib.flip(); // rib.position(0); // rob.clear(); rob.limit(lim); // for (CharBuffer ib : new CharBuffer[] { rib, dib }) { // Result r = recode(ib, rob); // if (! ((r.cr.isUnmappable() && // r.cr.length() == 2 && // rob.position() == 0) // || // (r.cr.isUnderflow() && // rob.position() > 0 && // ib.position() == 2))) { // if (failures++ > 5) return; // bug("Legal supplementary character bug: %s %s", // cs, r); // } // } // } // } // }
Result recode(CharBuffer ib, ByteBuffer ob) { try { byte canary = 22;
ib.clear(); // Prepare to read
ob.clear(); // Prepare to write for (int i = 0; i < ob.limit(); i++)
ob.put(i, canary);
CharsetEncoder coder = cs.newEncoder();
CoderResult cr = coder.encode(ib, ob, false);
equal(ib.limit(), ib.capacity());
equal(ob.limit(), ob.capacity());
Result r = new Result(ib, ob, cr); if (cr.isError())
check(cr.length() > 0); if (cr.isOverflow() && ob.remaining() > 10)
bug("OVERFLOW, but there's lots of room: %s %s",
cs, r); // if (cr.isOverflow() && ib.remaining() == 0 && ! hasBom) // bug("OVERFLOW, yet remaining() == 0: %s %s", // cs, r); if (cr.isError() && ib.remaining() < cr.length())
bug("remaining() < CoderResult.length(): %s %s",
cs, r); // if (ib.position() == 0 // && ob.position() > 0 // && ! hasBom(r.oa)) // bug("output only if input consumed: %s %s", // cs, r);
CoderResult cr2 = coder.encode(ib, ob, false); if (ib.position() != r.ipos ||
ob.position() != r.oa.length ||
cr != cr2)
bug("Coding operation not idempotent: %s%n %s%n %s",
cs, r, new Result(ib, ob, cr2)); if (ob.position() < ob.limit() &&
ob.get(ob.position()) != canary)
bug("Buffer overrun: %s %s %s",
cs, r, ob.get(ob.position())); return r;
} catch (Throwable t) { if (bug("Unexpected exception: %s %s %s",
cs, t.getClass().getSimpleName(), new Result(ib, ob, null)))
t.printStackTrace(); returnnull;
}
}
Result recode2(char[] ia, int n) { int len = ia.length;
CharBuffer rib = CharBuffer.wrap(ia);
CharBuffer dib = dInBuffers[len];
dib.clear(); dib.put(ia); dib.clear();
ByteBuffer rob = rOuBuffers[n];
ByteBuffer dob = dOuBuffers[n];
equal(rob.limit(), n);
equal(dob.limit(), n);
check(dib.isDirect());
check(dob.isDirect());
Result r1 = recode(rib, rob);
Result r2 = recode(dib, dob); if (r1 != null && r2 != null && ! Result.eq(r1, r2))
bug("Results differ for direct buffers: %s%n %s%n %s",
cs, r1, r2); return r1;
}
Result test(char[] ia) { if (failed - failed0 >= maxCharsetFailures) thrownew TooManyFailures();
Result roomy = recode2(ia, maxBufSize - 1); if (roomy == null) return roomy; int olen = roomy.oa.length; if (olen > 0) { if (roomy.ipos == roomy.ia.length) {
Result perfectFit = recode2(ia, olen); if (! Result.eq(roomy, perfectFit))
bug("Results differ: %s%n %s%n %s",
cs, roomy, perfectFit);
} for (int i = 0; i < olen; i++) {
Result claustrophobic = recode2(ia, i); if (claustrophobic == null) return roomy; if (roomy.cr.isUnderflow() &&
! claustrophobic.cr.isOverflow())
bug("Expected OVERFLOW: %s%n %s%n %s",
cs, roomy, claustrophobic);
}
} return roomy;
}
void testExhaustively(char[] prefix, int n) { int len = prefix.length; char[] ia = Arrays.copyOf(prefix, len + 1); for (int i = 0; i < 0x10000; i++) {
ia[len] = (char) i; if (n == 1)
test(ia); else
testExhaustively(ia, n - 1);
}
}
void testRandomly(char[] prefix, int n) { int len = prefix.length; char[] ia = Arrays.copyOf(prefix, len + n); for (int i = 0; i < 10000; i++) { for (int j = 0; j < n; j++)
ia[len + j] = randomChar();
test(ia);
}
}
void testISO88591InvalidChar() { // Several architectures implement the ISO-8859-1 encoder as an // intrinsic where the vectorised assembly has separate cases // for different input sizes, so exhaustively test all sizes // from 0 to maxBufSize to ensure we get coverage
for (int i = 0; i < CharsetTester.maxBufSize; i++) { char[] ia = newchar[i]; for (int j = 0; j < i; j++)
ia[j] = randomChar();
test(ia);
// Test break on unrepresentable character for (int j = 0; j < i; j++) { char[] iaInvalid = ia.clone();
iaInvalid[j] = (char)(randomChar() | 0x100);
test(iaInvalid);
}
}
}
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 und die Messung sind noch experimentell.