summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2025-06-25 16:23:23 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2025-06-25 16:23:23 (GMT)
commitea836428c1750ea8de38efcbe0633a4109b8c76a (patch)
tree1ace984257fad0be3b8f28942b2865a65cb866a5
parentafdd41dd6a5d3906527159c52769e985c45c11c1 (diff)
parent7b258bd47cb3dff4315697aaabf9d4920769f181 (diff)
downloadtcl-ea836428c1750ea8de38efcbe0633a4109b8c76a.zip
tcl-ea836428c1750ea8de38efcbe0633a4109b8c76a.tar.gz
tcl-ea836428c1750ea8de38efcbe0633a4109b8c76a.tar.bz2
Fix [7c2716733a] - use after free on Windows pipe handles
-rw-r--r--tests/aaa_exit.test12
-rw-r--r--tests/chanio.test10
-rw-r--r--tests/clock.test21
-rw-r--r--tests/cmdMZ.test9
-rw-r--r--tests/env.test3
-rw-r--r--win/tclWinInt.h3
-rw-r--r--win/tclWinPipe.c26
-rw-r--r--win/tclWinSerial.c3
8 files changed, 44 insertions, 43 deletions
diff --git a/tests/aaa_exit.test b/tests/aaa_exit.test
index 324c7a8..5957640 100644
--- a/tests/aaa_exit.test
+++ b/tests/aaa_exit.test
@@ -16,7 +16,11 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
-test exit-1.1 {normal, quick exit} {
+testConstraint noappverifier [expr {
+ [llength [info commands testappverifierpresent]] == 0
+ || ![testappverifierpresent]}]
+
+test exit-1.1 {normal, quick exit} -constraints noappverifier -body {
set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 0;exit}\"" r]
set aft [after 1000 {set done "Quick exit hangs !!!"}]
fileevent $f readable {after cancel $aft;set done OK}
@@ -30,9 +34,9 @@ test exit-1.1 {normal, quick exit} {
}
}
set done
-} OK
+} -result OK
-test exit-1.2 {full-finalized exit} {
+test exit-1.2 {full-finalized exit} -constraints noappverifier -body {
set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 1;exit}\"" r]
set aft [after 1000 {set done "Full-finalized exit hangs !!!"}]
fileevent $f readable {after cancel $aft;set done OK}
@@ -46,7 +50,7 @@ test exit-1.2 {full-finalized exit} {
}
}
set done
-} OK
+} -result OK
# cleanup
diff --git a/tests/chanio.test b/tests/chanio.test
index 704b887..da850f4 100644
--- a/tests/chanio.test
+++ b/tests/chanio.test
@@ -18,6 +18,10 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
+testConstraint noappverifier [expr {
+ [llength [info commands testappverifierpresent]] == 0
+ || ![testappverifierpresent]}]
+
namespace eval ::tcl::test::io {
if {"::tcltest" ni [namespace children]} {
@@ -1039,7 +1043,7 @@ test chan-io-6.55 {Tcl_GetsObj: overconverted} -body {
test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup {
update
variable x {}
-} -constraints {stdio fileevent} -body {
+} -constraints {stdio fileevent noappverifier} -body {
set f [openpipe w+ $path(cat)]
chan configure $f -buffering none
chan puts -nonewline $f "foobar"
@@ -1476,7 +1480,7 @@ test chan-io-13.5 {TranslateInputEOL: crlf mode: naked lf} -body {
test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} -setup {
variable x {}
variable y {}
-} -constraints {stdio testchannel fileevent} -body {
+} -constraints {stdio testchannel fileevent noappverifier} -body {
# (chanPtr->flags & INPUT_SAW_CR)
# This test may fail on slower machines.
set f [openpipe w+ $path(cat)]
@@ -2198,7 +2202,7 @@ test chan-io-28.6 {Tcl_CloseEx (half-close) pipe} -setup {
exit 0
} cat.tcl]
variable done
-} -body {
+} -constraints noappverifier -body {
set ff [openpipe r+ $cat]
puts $ff Hey
close $ff w
diff --git a/tests/clock.test b/tests/clock.test
index b69808c..e1bbc88 100644
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -25,6 +25,13 @@ if {[testConstraint win]} {
}
}
+# Application Verifier hooks system calls in a way that locale
+# detection fails. Disable tests that depend on that if
+# it is running.
+testConstraint noappverifier [expr {
+ [llength [info commands testappverifierpresent]] == 0
+ || ![testappverifierpresent]}]
+
package require msgcat 1.4
testConstraint detroit \
@@ -35943,7 +35950,7 @@ test clock-30.34 {regression test - clock add jump over DST hole with TZ (1 day
test clock-31.1 {system locale} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
@@ -35966,7 +35973,7 @@ test clock-31.1 {system locale} \
-format {%d-%b-%Y}]
test clock-31.2 {system locale} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
@@ -35989,7 +35996,7 @@ test clock-31.2 {system locale} \
-format {the %d' day of %B %Y}]
test clock-31.3 {system locale} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
@@ -36012,7 +36019,7 @@ test clock-31.3 {system locale} \
-format {%l:%M:%S %p}]
test clock-31.4 {system locale} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
@@ -36049,7 +36056,7 @@ test clock-31.4 {system locale} \
-format {%d-%b-%Y}]
test clock-31.5 {system locale} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
@@ -36086,7 +36093,7 @@ test clock-31.5 {system locale} \
-format {the %d' day of %B %Y}]
test clock-31.6 {system locale} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
namespace eval ::tcl::clock {
namespace import -force ::testClock::registry
@@ -37548,7 +37555,7 @@ test clock-49.1 {regression test - localtime with negative arg (Bug 1237907)} \
-result {0 1969|1 {localtime failed \(clock value may be too large/small to represent\)}}
test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \
- -constraints win \
+ -constraints {win noappverifier} \
-setup {
# override the registry so that the test takes place in New York time
namespace eval ::tcl::clock {
diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test
index ff282b7..3f764a0 100644
--- a/tests/cmdMZ.test
+++ b/tests/cmdMZ.test
@@ -16,6 +16,10 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
+testConstraint noappverifier [expr {
+ [llength [info commands testappverifierpresent]] == 0
+ || ![testappverifierpresent]}]
+
namespace eval ::tcl::test::cmdMZ {
namespace import ::tcltest::cleanupTests
namespace import ::tcltest::customMatch
@@ -420,7 +424,10 @@ test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} {
test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} {
regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0]
} 1
-test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measurement} -body {
+test cmdMZ-6.6 {
+ Tcl_TimeRateObjCmd: slower commands take longer, but it
+ remains almost the same time of measurement
+} -constraints noappverifier -body {
set m1 [timerate {_nrt_sleep 0.01} 50]
set m2 [timerate {_nrt_sleep 1.00} 50]
if {[testConstraint valgrind] && ([lindex $m1 0] >= 100 || [lindex $m1 2] <= 500)} {
diff --git a/tests/env.test b/tests/env.test
index 8b3f1df..2534278 100644
--- a/tests/env.test
+++ b/tests/env.test
@@ -102,12 +102,13 @@ proc cleanup1 {} {
envrestore
}
+# OANOCACHE comes from Application Verifier
variable keep {
TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM
__CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
- CommonProgramFiles CommonProgramFiles(x86) ProgramFiles
+ CommonProgramFiles CommonProgramFiles(x86) OANOCACHE ProgramFiles
ProgramFiles(x86) CommonProgramW6432 ProgramW6432
PROCESSOR_ARCHITECTURE PROCESSOR_ARCHITEW6432 USERPROFILE
WINECONFIGDIR WINEDATADIR WINEDLLDIR0 WINEHOMEDIR
diff --git a/win/tclWinInt.h b/win/tclWinInt.h
index 2c702fb..3ba3c57 100644
--- a/win/tclWinInt.h
+++ b/win/tclWinInt.h
@@ -76,7 +76,6 @@ typedef struct TclPipeThreadInfo {
* 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 */
- HANDLE evWakeUp; /* Optional wake-up event worker set by shutdown */
} TclPipeThreadInfo;
/* If pipe-workers will use some tcl subsystem, we can use Tcl_Alloc without
@@ -101,7 +100,7 @@ enum PipeWorkerStates {
MODULE_SCOPE
TclPipeThreadInfo * TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr,
- void *clientData, HANDLE wakeEvent);
+ void *clientData);
MODULE_SCOPE int TclPipeThreadWaitForSignal(
TclPipeThreadInfo **pipeTIPtr);
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index 2aa6d98..a2b630a 100644
--- a/win/tclWinPipe.c
+++ b/win/tclWinPipe.c
@@ -1817,8 +1817,7 @@ TclpCreateCommandChannel(
infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL);
infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread,
- TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr, infoPtr->readable),
- 0, NULL);
+ TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr), 0, NULL);
SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);
infoPtr->validMask |= TCL_READABLE;
} else {
@@ -1832,8 +1831,7 @@ TclpCreateCommandChannel(
infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL);
infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread,
- TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr, infoPtr->writable),
- 0, NULL);
+ TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL);
SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST);
infoPtr->validMask |= TCL_WRITABLE;
} else {
@@ -3301,8 +3299,7 @@ TclpOpenTemporaryFile(
TclPipeThreadInfo *
TclPipeThreadCreateTI(
TclPipeThreadInfo **pipeTIPtr,
- void *clientData,
- HANDLE wakeEvent)
+ void *clientData)
{
TclPipeThreadInfo *pipeTI;
#ifndef _PTI_USE_CKALLOC
@@ -3313,7 +3310,6 @@ TclPipeThreadCreateTI(
pipeTI->evControl = CreateEventW(NULL, FALSE, FALSE, NULL);
pipeTI->state = PTI_STATE_IDLE;
pipeTI->clientData = clientData;
- pipeTI->evWakeUp = wakeEvent;
return (*pipeTIPtr = pipeTI);
}
@@ -3341,14 +3337,11 @@ TclPipeThreadWaitForSignal(
TclPipeThreadInfo *pipeTI = *pipeTIPtr;
LONG state;
DWORD waitResult;
- HANDLE wakeEvent;
if (!pipeTI) {
return 0;
}
- wakeEvent = pipeTI->evWakeUp;
-
/*
* Wait for the main thread to signal before attempting to do the work.
*/
@@ -3408,11 +3401,6 @@ TclPipeThreadWaitForSignal(
if (state != PTI_STATE_STOP) {
*pipeTIPtr = NULL;
- } else {
- pipeTI->evWakeUp = NULL;
- }
- if (wakeEvent) {
- SetEvent(wakeEvent);
}
return 0;
}
@@ -3446,7 +3434,6 @@ TclPipeThreadStopSignal(
return 1;
}
evControl = pipeTI->evControl;
- pipeTI->evWakeUp = wakeEvent;
state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
PTI_STATE_IDLE);
switch (state) {
@@ -3510,7 +3497,6 @@ TclPipeThreadStop(
}
pipeTI = *pipeTIPtr;
evControl = pipeTI->evControl;
- pipeTI->evWakeUp = NULL;
/*
* Try to sane stop the pipe worker, corresponding its current state
@@ -3662,9 +3648,6 @@ TclPipeThreadStop(
*pipeTIPtr = NULL;
if (pipeTI) {
- if (pipeTI->evWakeUp) {
- SetEvent(pipeTI->evWakeUp);
- }
CloseHandle(pipeTI->evControl);
#ifndef _PTI_USE_CKALLOC
free(pipeTI);
@@ -3713,9 +3696,6 @@ TclPipeThreadExit(
state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN);
if (state == PTI_STATE_STOP) {
CloseHandle(pipeTI->evControl);
- if (pipeTI->evWakeUp) {
- SetEvent(pipeTI->evWakeUp);
- }
#ifndef _PTI_USE_CKALLOC
free(pipeTI);
#else
diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c
index 690183c..48baaa8 100644
--- a/win/tclWinSerial.c
+++ b/win/tclWinSerial.c
@@ -1506,8 +1506,7 @@ TclWinOpenSerialChannel(
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,
- infoPtr->evWritable), 0, NULL);
+ TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL);
}
Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");