Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Bug [7c2716733a] - use after free on Windows event handle |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | bug-7c2716733a |
Files: | files | file ages | folders |
SHA3-256: |
e85c44529a9b3d580f7701dce8f72ee0 |
User & Date: | apnadkarni 2025-06-14 13:59:53.617 |
Context
2025-06-15
| ||
10:15 | Fat fingers in constraints check-in: c1f1232e47 user: apnadkarni tags: bug-7c2716733a | |
2025-06-14
| ||
13:59 | Bug [7c2716733a] - use after free on Windows event handle check-in: e85c44529a user: apnadkarni tags: bug-7c2716733a | |
13:59 | Disable additional tests under App Verifier - timing or locale do not work with it check-in: d8dd42f87f user: apnadkarni tags: bug-7c2716733a | |
Changes
Changes to win/tclWinInt.h.
︙ | ︙ | |||
72 73 74 75 76 77 78 | typedef struct TclPipeThreadInfo { HANDLE evControl; /* Auto-reset event used by the main thread to * signal when the pipe thread should attempt * to do read/write operation. Additionally * used as signal to stop (state set to -1) */ volatile LONG state; /* Indicates current state of the thread */ void *clientData; /* Referenced data of the main thread */ | < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | typedef struct TclPipeThreadInfo { HANDLE evControl; /* Auto-reset event used by the main thread to * signal when the pipe thread should attempt * to do read/write operation. Additionally * used as signal to stop (state set to -1) */ volatile LONG state; /* Indicates current state of the thread */ void *clientData; /* Referenced data of the main thread */ } TclPipeThreadInfo; /* If pipe-workers will use some tcl subsystem, we can use Tcl_Alloc without * more overhead for finalize thread (should be executed anyway) * * #define _PTI_USE_CKALLOC 1 */ |
︙ | ︙ | |||
97 98 99 100 101 102 103 | PTI_STATE_STOP = 2, /* thread should stop work (owns TI structure) */ PTI_STATE_END = 4, /* thread should stop work (worker is busy) */ PTI_STATE_DOWN = 8 /* worker is down */ }; MODULE_SCOPE TclPipeThreadInfo * TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr, | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | PTI_STATE_STOP = 2, /* thread should stop work (owns TI structure) */ PTI_STATE_END = 4, /* thread should stop work (worker is busy) */ PTI_STATE_DOWN = 8 /* worker is down */ }; MODULE_SCOPE TclPipeThreadInfo * TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr, void *clientData); MODULE_SCOPE int TclPipeThreadWaitForSignal( TclPipeThreadInfo **pipeTIPtr); static inline void TclPipeThreadSignal( TclPipeThreadInfo **pipeTIPtr) { |
︙ | ︙ |
Changes to win/tclWinPipe.c.
︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | if (readFile != NULL) { /* * Start the background reader thread. */ infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread, | | < | < | 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 | if (readFile != NULL) { /* * Start the background reader thread. */ infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread, TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr), 0, NULL); SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST); infoPtr->validMask |= TCL_READABLE; } else { infoPtr->readTI = NULL; infoPtr->readThread = 0; } if (writeFile != NULL) { /* * Start the background writer thread. */ infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread, TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL); SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST); infoPtr->validMask |= TCL_WRITABLE; } else { infoPtr->writeTI = NULL; infoPtr->writeThread = 0; } |
︙ | ︙ | |||
3297 3298 3299 3300 3301 3302 3303 | * *---------------------------------------------------------------------- */ TclPipeThreadInfo * TclPipeThreadCreateTI( TclPipeThreadInfo **pipeTIPtr, | | < < | 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 | * *---------------------------------------------------------------------- */ TclPipeThreadInfo * TclPipeThreadCreateTI( TclPipeThreadInfo **pipeTIPtr, void *clientData) { TclPipeThreadInfo *pipeTI; #ifndef _PTI_USE_CKALLOC pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo)); #else pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo)); #endif /* !_PTI_USE_CKALLOC */ pipeTI->evControl = CreateEventW(NULL, FALSE, FALSE, NULL); pipeTI->state = PTI_STATE_IDLE; pipeTI->clientData = clientData; return (*pipeTIPtr = pipeTI); } /* *---------------------------------------------------------------------- * * TclPipeThreadWaitForSignal -- |
︙ | ︙ | |||
3337 3338 3339 3340 3341 3342 3343 | int TclPipeThreadWaitForSignal( TclPipeThreadInfo **pipeTIPtr) { TclPipeThreadInfo *pipeTI = *pipeTIPtr; LONG state; DWORD waitResult; | < < < | 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 | int TclPipeThreadWaitForSignal( TclPipeThreadInfo **pipeTIPtr) { TclPipeThreadInfo *pipeTI = *pipeTIPtr; LONG state; DWORD waitResult; if (!pipeTI) { return 0; } /* * Wait for the main thread to signal before attempting to do the work. */ /* * Reset work state of thread (idle/waiting) */ |
︙ | ︙ | |||
3404 3405 3406 3407 3408 3409 3410 | end: /* * End of work, check the owner of the TI structure. */ if (state != PTI_STATE_STOP) { *pipeTIPtr = NULL; | < < < < < | 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 | end: /* * End of work, check the owner of the TI structure. */ if (state != PTI_STATE_STOP) { *pipeTIPtr = NULL; } return 0; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3442 3443 3444 3445 3446 3447 3448 | HANDLE evControl; int state; if (!pipeTI) { return 1; } evControl = pipeTI->evControl; | < | 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 | HANDLE evControl; int state; if (!pipeTI) { return 1; } evControl = pipeTI->evControl; state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP, PTI_STATE_IDLE); switch (state) { case PTI_STATE_IDLE: /* * Thread was idle/waiting, notify it goes teardown */ |
︙ | ︙ | |||
3506 3507 3508 3509 3510 3511 3512 | int state; if (!pipeTI) { return; } pipeTI = *pipeTIPtr; evControl = pipeTI->evControl; | < | 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 | int state; if (!pipeTI) { return; } pipeTI = *pipeTIPtr; evControl = pipeTI->evControl; /* * Try to sane stop the pipe worker, corresponding its current state */ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP, PTI_STATE_IDLE); |
︙ | ︙ | |||
3658 3659 3660 3661 3662 3663 3664 | } } } } *pipeTIPtr = NULL; if (pipeTI) { | < < < | 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 | } } } } *pipeTIPtr = NULL; if (pipeTI) { CloseHandle(pipeTI->evControl); #ifndef _PTI_USE_CKALLOC free(pipeTI); #else Tcl_Free(pipeTI); #endif /* !_PTI_USE_CKALLOC */ } |
︙ | ︙ | |||
3709 3710 3711 3712 3713 3714 3715 | if (!pipeTI) { return; } *pipeTIPtr = NULL; state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN); if (state == PTI_STATE_STOP) { CloseHandle(pipeTI->evControl); | < < < | 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 | if (!pipeTI) { return; } *pipeTIPtr = NULL; state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN); if (state == PTI_STATE_STOP) { CloseHandle(pipeTI->evControl); #ifndef _PTI_USE_CKALLOC free(pipeTI); #else Tcl_Free(pipeTI); /* be sure all subsystems used are finalized */ Tcl_FinalizeThread(); #endif /* !_PTI_USE_CKALLOC */ |
︙ | ︙ |
Changes to win/tclWinSerial.c.
︙ | ︙ | |||
1502 1503 1504 1505 1506 1507 1508 | /* * Initially the channel is writable and the writeThread is idle. */ infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread, | | < | 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 | /* * Initially the channel is writable and the writeThread is idle. */ infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread, TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL); } Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); return infoPtr->channel; } |
︙ | ︙ |