Fix mbedTLS is_peer_closed() destroying the first response byte

Mbed TLS has no SSL_peek() equivalent, so is_peer_closed() (called after
every SSL request write) probed liveness with a real 1-byte
mbedtls_ssl_read() and discarded whatever it read. If the response had
already arrived by the time the probe ran — plausible under CI load or
plain OS scheduling — the probe silently ate the first byte of the
status line, corrupting the response and surfacing as a fast
"Failed to read connection" failure.

This was the root cause of the long-standing MbedTLS-only CI flakiness
(ServerTest cases failing intermittently on Ubuntu and macOS), previously
worked around by reducing gtest shard parallelism. Fix: push the probed
byte back into MbedTlsSession and have tls::read()/pending() account for
it, so no data is lost.

Also fix a second, unrelated flake: ProxyTunnelTest.
OriginReturning407InsideTunnelDoesNotLeakProxyDigest used "localhost" for
its client while the test's proxy harness only listens on 127.0.0.1;
under dual-stack resolution this could race with another test's server
on ::1 using the same ephemeral port. Pin the test to 127.0.0.1.

With the root cause fixed, restore the mbedTLS CI jobs (ubuntu,
ubuntu-26.04, macOS) to the default shard count instead of the
previously reduced SHARDS=1/2 mitigation.
This commit is contained in:
yhirose
2026-07-23 22:41:43 -04:00
parent 82b1492c3d
commit 2fa0417754
3 changed files with 50 additions and 23 deletions
+6 -2
View File
@@ -20893,9 +20893,13 @@ TEST(ProxyTunnelTest, OriginReturning407InsideTunnelDoesNotLeakProxyDigest) {
proxy_tunnel_test::ScopedConnectProxy proxy(origin.port());
ASSERT_NE(0, proxy.port());
SSLClient cli(HOST, origin.port());
// Pin to 127.0.0.1: the proxy listens on 127.0.0.1 only, while "localhost"
// may resolve to ::1 first. A concurrent test (e.g. another gtest shard)
// holding ::1 with the same ephemeral port number would hijack the CONNECT
// and answer with its own status, making this test flaky.
SSLClient cli("127.0.0.1", origin.port());
cli.enable_server_certificate_verification(false);
cli.set_proxy(HOST, proxy.port());
cli.set_proxy("127.0.0.1", proxy.port());
cli.set_proxy_digest_auth("proxy-user", "proxy-pass");
auto res = cli.Get("/x");