@@ -10458,6 +10458,57 @@ TEST(SSLTest, ErrorSyscallAfterCloseNotify) {
10458
10458
write_failed = false;
10459
10459
}
10460
10460
10461
+ // Test that intermittent inability to read results in retryable error
10462
+ TEST(SSLTest, IntermittentEmptyRead) {
10463
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
10464
+ bssl::UniquePtr<SSL_CTX> server_ctx =
10465
+ CreateContextWithTestCertificate(TLS_method());
10466
+ ASSERT_TRUE(client_ctx);
10467
+ ASSERT_TRUE(server_ctx);
10468
+ bssl::UniquePtr<SSL> client, server;
10469
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
10470
+ server_ctx.get()));
10471
+
10472
+ // Create a fake read BIO that returns 0 on read to simulate empty read
10473
+ bssl::UniquePtr<BIO_METHOD> method(BIO_meth_new(0, nullptr));
10474
+ ASSERT_TRUE(method);
10475
+ BIO_meth_set_create(method.get(), [](BIO *b) -> int {
10476
+ BIO_set_init(b, 1);
10477
+ return 1;
10478
+ });
10479
+ BIO_meth_set_read(method.get(), [](BIO *, char *, int) -> int {
10480
+ return 0;
10481
+ });
10482
+ bssl::UniquePtr<BIO> rbio_empty(BIO_new(method.get()));
10483
+ ASSERT_TRUE(rbio_empty);
10484
+ BIO_set_flags(rbio_empty.get(), BIO_FLAGS_READ);
10485
+
10486
+ // Save off client rbio and use empty read BIO
10487
+ bssl::UniquePtr<BIO> client_rbio(SSL_get_rbio(client.get()));
10488
+ ASSERT_TRUE(client_rbio);
10489
+ // Up-ref |client_rbio| as SSL_CTX dtor will also attempt to free it
10490
+ ASSERT_TRUE(BIO_up_ref(client_rbio.get()));
10491
+ SSL_set0_rbio(client.get(), rbio_empty.release());
10492
+
10493
+ // Server writes some data to the client
10494
+ const uint8_t data[1] = {0};
10495
+ int ret = SSL_write(server.get(), data, (int) sizeof(data));
10496
+ EXPECT_EQ(ret, (int) sizeof(data));
10497
+ EXPECT_EQ(SSL_get_error(server.get(), ret), SSL_ERROR_NONE);
10498
+
10499
+ // On empty read, client should still want a read so caller will retry
10500
+ uint8_t buf[1];
10501
+ ret = SSL_read(client.get(), buf, sizeof(buf));
10502
+ EXPECT_EQ(ret, 0);
10503
+ EXPECT_EQ(SSL_get_error(client.get(), ret), SSL_ERROR_WANT_READ);
10504
+
10505
+ // Reset client rbio, read should succeed
10506
+ SSL_set0_rbio(client.get(), client_rbio.release());
10507
+ ret = SSL_read(client.get(), buf, sizeof(buf));
10508
+ EXPECT_EQ(ret, (int) sizeof(buf));
10509
+ EXPECT_EQ(SSL_get_error(client.get(), ret), SSL_ERROR_NONE);
10510
+ }
10511
+
10461
10512
// Test that |SSL_shutdown|, when quiet shutdown is enabled, simulates receiving
10462
10513
// a close_notify, down to |SSL_read| reporting |SSL_ERROR_ZERO_RETURN|.
10463
10514
TEST(SSLTest, QuietShutdown) {
0 commit comments