8239052: java/net/httpclient/whitebox/SSLEchoTubeTestDriver.java failed with BufferUnderflowException against TLSv1.3

The test assumed that ByteBuffer would be split at long boundaries. This is obviously not always the case. A carry has been added to support reading a long split over several buffers.

Reviewed-by: chegar
This commit is contained in:
Daniel Fuchs 2020-02-24 17:19:32 +00:00
parent 965e330cb4
commit f7c819a72d
2 changed files with 68 additions and 3 deletions

View File

@ -49,6 +49,7 @@ import javax.net.ssl.SSLSocket;
/**
* @test
* @bug 8238990
* @run main/othervm -Djdk.internal.httpclient.debug=true HandshakeFailureTest TLSv1.2
* @run main/othervm -Djdk.internal.httpclient.debug=true HandshakeFailureTest TLSv1.3
* @summary Verify SSLHandshakeException is received when the handshake fails,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, 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
@ -126,6 +126,7 @@ public class AbstractSSLTubeTest extends AbstractRandomTest {
protected static class EndSubscriber implements FlowTube.TubeSubscriber {
private static final int REQUEST_WINDOW = 13;
private static final int SIZEOF_LONG = 8;
private final long nbytes;
private final AtomicLong counter = new AtomicLong();
@ -133,12 +134,16 @@ public class AbstractSSLTubeTest extends AbstractRandomTest {
private final CountDownLatch allBytesReceived;
private volatile Flow.Subscription subscription;
private long unfulfilled;
private final ByteBuffer carry; // used if buffers don't break at long boundaries.
EndSubscriber(long nbytes, CompletableFuture<?> completion,
CountDownLatch allBytesReceived) {
this.nbytes = nbytes;
this.completion = completion;
this.allBytesReceived = allBytesReceived;
this.carry = ByteBuffer.allocate(SIZEOF_LONG);
carry.position(carry.limit());
}
@Override
@ -159,6 +164,56 @@ public class AbstractSSLTubeTest extends AbstractRandomTest {
return sb.toString();
}
// Check whether we need bytes from the next buffer to read
// the next long. If yes, drains the current buffer into the
// carry and returns true. If no and the current buffer
// or the carry have enough bytes to read a long, return
// false.
private boolean requiresMoreBytes(ByteBuffer buf) {
// First see if the carry contains some left over bytes
// from the previous buffer
if (carry.hasRemaining()) {
// If so fills up the carry, if we can
while (carry.hasRemaining() && buf.hasRemaining()) {
carry.put(buf.get());
}
if (!carry.hasRemaining()) {
// The carry is full: we can use it.
carry.flip();
return false;
} else {
// There was not enough bytes to fill the carry,
// continue with next buffer.
assert !buf.hasRemaining();
return true;
}
} else if (buf.remaining() < SIZEOF_LONG) {
// The carry is empty and the current buffer doesn't
// have enough bytes: drains it into the carry.
carry.clear();
carry.put(buf);
assert carry.hasRemaining();
assert !buf.hasRemaining();
// We still need more bytes from the next buffer.
return true;
}
// We have enough bytes to read a long. No need
// to read from next buffer.
assert buf.remaining() >= SIZEOF_LONG;
return false;
}
private long readNextLong(ByteBuffer buf) {
// either the carry is ready to use (it must have 8 bytes to read)
// or it must be used up and at the limit.
assert !carry.hasRemaining() || carry.remaining() == SIZEOF_LONG;
// either we have a long in the carry, or we have enough bytes in the buffer
assert carry.remaining() == SIZEOF_LONG || buf.remaining() >= SIZEOF_LONG;
ByteBuffer source = carry.hasRemaining() ? carry : buf;
return source.getLong();
}
@Override
public void onNext(List<ByteBuffer> buffers) {
if (--unfulfilled == (REQUEST_WINDOW / 2)) {
@ -176,7 +231,17 @@ public class AbstractSSLTubeTest extends AbstractRandomTest {
for (ByteBuffer buf : buffers) {
while (buf.hasRemaining()) {
long n = buf.getLong();
// first check if we have enough bytes to
// read a long. If not, place the bytes in
// the carry and continue with next buffer.
if (requiresMoreBytes(buf)) continue;
// either we have a long in the carry, or we have
// enough bytes in the buffer to read a long.
long n = readNextLong(buf);
assert !carry.hasRemaining();
if (currval > (TOTAL_LONGS - 50)) {
System.out.println("End: " + currval);
}
@ -225,7 +290,6 @@ public class AbstractSSLTubeTest extends AbstractRandomTest {
SSLContext context = (new SimpleSSLContext()).get();
SSLEngine engine = context.createSSLEngine();
SSLParameters params = context.getSupportedSSLParameters();
params.setProtocols(new String[]{"TLSv1.2"}); // TODO: This is essential. Needs to be protocol impl
if (client) {
params.setApplicationProtocols(new String[]{"proto1", "proto2"}); // server will choose proto2
} else {