summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2010-01-18 22:20:56 (GMT)
committerandreas_kupries <akupries@shaw.ca>2010-01-18 22:20:56 (GMT)
commit0de317d573fcb3c53eae3f6e5c8587b36968651c (patch)
treee2562b1a5772d51eeec66d4ead8d3b7ff19393b5 /generic
parenta01c81316c6cdad00e46f0224b7bfe4b52078ad8 (diff)
downloadtcl-0de317d573fcb3c53eae3f6e5c8587b36968651c.zip
tcl-0de317d573fcb3c53eae3f6e5c8587b36968651c.tar.gz
tcl-0de317d573fcb3c53eae3f6e5c8587b36968651c.tar.bz2
* generic/tclIO.c (CreateScriptRecord): [Bug 2918110]: Initialize
the EventScriptRecord (esPtr) fully before handing it to Tcl_CreateChannelHandler for registration. Otherwise a reflected channel calling 'chan postevent' (== Tcl_NotifyChannel) in its 'watchProc' will cause the function 'TclChannelEventScriptInvoker' to be run on an uninitialized structure.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclIO.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index b072cbf..1c3ba79 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIO.c,v 1.137.2.15 2009/11/12 17:03:02 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclIO.c,v 1.137.2.16 2010/01/18 22:20:56 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -8268,6 +8268,7 @@ CreateScriptRecord(
ChannelState *statePtr = chanPtr->state;
/* State info for channel */
EventScriptRecord *esPtr;
+ int makeCH;
for (esPtr=statePtr->scriptRecordPtr; esPtr!=NULL; esPtr=esPtr->nextPtr) {
if ((esPtr->interp == interp) && (esPtr->mask == mask)) {
@@ -8276,18 +8277,34 @@ CreateScriptRecord(
break;
}
}
- if (esPtr == NULL) {
+
+ makeCH = (esPtr == NULL);
+
+ if (makeCH) {
esPtr = (EventScriptRecord *) ckalloc(sizeof(EventScriptRecord));
- Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
- TclChannelEventScriptInvoker, esPtr);
- esPtr->nextPtr = statePtr->scriptRecordPtr;
- statePtr->scriptRecordPtr = esPtr;
}
+
+ /*
+ * Initialize the structure before calling Tcl_CreateChannelHandler,
+ * because a reflected channel caling 'chan postevent' aka
+ * 'Tcl_NotifyChannel' in its 'watch'Proc will invoke
+ * 'TclChannelEventScriptInvoker' immediately, and we do not wish it to
+ * see uninitialized memory and crash. See [Bug 2918110].
+ */
+
esPtr->chanPtr = chanPtr;
esPtr->interp = interp;
esPtr->mask = mask;
Tcl_IncrRefCount(scriptPtr);
esPtr->scriptPtr = scriptPtr;
+
+ if (makeCH) {
+ esPtr->nextPtr = statePtr->scriptRecordPtr;
+ statePtr->scriptRecordPtr = esPtr;
+
+ Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask,
+ TclChannelEventScriptInvoker, esPtr);
+ }
}
/*