Bug #115572 CancellationToken causes unhandled exception crash when in StartSSLAsync
Submitted: 12 Jul 9:51 Modified: 12 Jul 13:15
Reporter: Brent Alleweireldt Email Updates:
Status: Duplicate Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:8.0.33 OS:Any
Assigned to: CPU Architecture:Any
Tags: SSL, timeout, Unhandled exception

[12 Jul 9:51] Brent Alleweireldt
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().
[12 Jul 9:56] Brent Alleweireldt
Clumsy settings

Attachment: clumsy settings.png (image/png, text), 26.90 KiB.

[12 Jul 13:15] Brent Alleweireldt
Duplicate-ish (same flow, just different exceptions of https://bugs.mysql.com/bug.php?id=110789. Apologies.
[15 Jul 11:57] MySQL Verification Team
Thank you for the feedback.