Tcl Source Code

View Ticket
Login
Ticket UUID: 7c2716733a526ba6d08eccbf27b6a07f8b081c
Title: App Verifier shows use-after-free on event handle for Windows pipes
Type: Bug Version: trunk
Submitter: apnadkarni Created on: 2025-06-13 11:13:49
Subsystem: - New Builtin Commands Assigned To: nobody
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2025-06-25 16:24:23
Resolution: Fixed Closed By: apnadkarni
    Closed on: 2025-06-25 16:24:23
Description:

Running the Windows application verifier on trunk shows a use after free on a Windows event handle used for exec pipes. The offending line is here.

The SetEvent generally returns an invalid handle error in this case and we happily ignore the error so it is undetected and life goes on. However, if by chance (however small) the handle value were to be reused by Windows for a different handle, unexpected behaviour would occur as it would not be treated as an invalid handle.

This should be afforded the same level of importance as a user-after-free detected by valgrind.

User Comments: apnadkarni added on 2025-06-25 16:24:23:
Fixed in [7c2716733a].

apnadkarni added on 2025-06-14 14:31:09:

Proposed fix is here.

Looking more closely at the code, I did not see why that event handle was needed at all. In summary,

  • the handle in question is TclPipeThreadInfo.evWakeup. This is initialized from the readable or writable event handles from the channel structure.

  • the worker thread however signal read or write completions directly using the readable/writable handles from the channel structure, not evWakeup.

  • the only time TclPipeThreadInfo.evWakeup is signalled is on worker thread exit which is when it has already been deallocated by the main thread causing the use-after-free error!

The proposed fix simply expunges all references to the TclPipeThreadInfo.evWakeup. The test suite passes and Application Verifier no longer complains. But someone should review before merge.


apnadkarni added on 2025-06-13 11:48:28:

Looking at the source, the event handle seems to have been already closed here.

It seems to me that the immediately preceding TclPipeThreadStop wakes up the worker thread, transitioning it to the STOP state where it invokes SetEvent(). In the meanwhile, the code after TclPipeThreadStop immediately closes that event handle before the worker actually runs. Hence the invalid handle error.

I don't know what the synchronization protocol is between the main and worker threads so leaving investigation and fix to those who do.

As an aside, seems like this extends way back to 8.6.