Description:
Discovered in 8.0.33 but still present in the latest version.
MySQL version 8.4
Connector version: 8.0.33-9.0.0
.Net framework: 4.8 (presumably also present in .Net 8.0)
The driver can throw an unhandled exception if the ConnectionTimeout expires during the AuthenticateAsClient part of the SSL initialization. This exception cannot be caught by the client and thus causes an application crash. (see detailed description below)
Expectations: Connector does not throw exceptions that cannot be handled.
Detailed description:
In Driver.cs->CreateAsync() a CancellationTokenSource (named connTimeoutSource) gets created that will be canceled after the connectionTimout has expired. The token from this connTimeoutSource is then linked to a general CancellationToken that is passed around during the connection-logic.
This token eventually ends up in Ssl.cs->StartSSLAsync(), right before starting the AuthenticateAsClientAsync() the Cancellationtoken gets used to register a callback that throws an IOException.
However if this token is cancelled by the timeout from the connTimeoutToken, This exception ends up on a timerthread and is not caught, leading to a crash of the application.
How to repeat:
Requires external tools to simulate properly.
1. Configure clumsy with the following settings
-Filter "tcp.DstPort == 3384 and tcp.PayloadLength >= 147" (basically TLS client hello)
- Enable drop on inbound/outbound with 100% chance
2. Connect a MySQL database with SSLMode=Preferred
3. Observe the unhandled exception.
Suggested fix:
Do not throw exceptions in the CancellationToken.Register function. Use other methods to properly detect if the timeout passed and throw the exception on the thread that called the Open().