/* * Copyright (c) 2008, 2017, 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 6380723 * @summary Decode many byte sequences in many ways (use -Dseed=X to set PRNG seed) * @library /test/lib * @build jdk.test.lib.RandomFactory * @run main/timeout=1800 FindDecoderBugs * @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);
}
Result recode(ByteBuffer ib, CharBuffer ob) { try { char canary = '\u4242';
ib.clear(); // Prepare to read
ob.clear(); // Prepare to write for (int i = 0; i < ob.limit(); i++)
ob.put(i, canary);
CharsetDecoder coder = cs.newDecoder();
CoderResult cr = coder.decode(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) // 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) // reporter. bug("output only if input consumed: %s %s", // cs, r); // Should we warn if cr.isUnmappable() ??
CoderResult cr2 = coder.decode(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(byte[] ia, int n) { int len = ia.length;
ByteBuffer rib = ByteBuffer.wrap(ia);
ByteBuffer dib = dibs[len];
dib.clear(); dib.put(ia); dib.clear();
CharBuffer rob = robs[n];
CharBuffer dob = dobs[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(byte[] 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(byte[] prefix, int n) { int len = prefix.length; byte[] ia = Arrays.copyOf(prefix, len + 1); for (int i = 0; i < 0x100; i++) {
ia[len] = (byte) i; if (n == 1)
test(ia); else
testExhaustively(ia, n - 1);
}
}
void testRandomly(byte[] prefix, int n) { int len = prefix.length; byte[] ia = Arrays.copyOf(prefix, len + n); for (int i = 0; i < 5000; i++) { for (int j = 0; j < n; j++)
ia[len + j] = randomByte();
test(ia);
}
}
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.