diff options
author | andreas_kupries <akupries@shaw.ca> | 2010-01-18 22:20:56 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2010-01-18 22:20:56 (GMT) |
commit | 0de317d573fcb3c53eae3f6e5c8587b36968651c (patch) | |
tree | e2562b1a5772d51eeec66d4ead8d3b7ff19393b5 | |
parent | a01c81316c6cdad00e46f0224b7bfe4b52078ad8 (diff) | |
download | tcl-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.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | generic/tclIO.c | 29 |
2 files changed, 32 insertions, 6 deletions
@@ -1,3 +1,12 @@ +2010-01-18 Andreas Kupries <andreask@activestate.com> + + * 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. + 2010-01-18 Donal K. Fellows <dkf@users.sf.net> * generic/tclStringObj.c (Tcl_AppendFormatToObj): [Bug 2932421]: Stop 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); + } } /* |