diff options
author | andreas_kupries <akupries@shaw.ca> | 2008-04-04 16:45:48 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2008-04-04 16:45:48 (GMT) |
commit | dd13549c2381c348b6536501d389e513a6082f5d (patch) | |
tree | df824fb86004bdab22bfe820fe7088ec3497714d /generic/tclIORChan.c | |
parent | f22c720323ae972ba91834691c7c0ad1b800d2df (diff) | |
download | tcl-dd13549c2381c348b6536501d389e513a6082f5d.zip tcl-dd13549c2381c348b6536501d389e513a6082f5d.tar.gz tcl-dd13549c2381c348b6536501d389e513a6082f5d.tar.bz2 |
* generic/tclIORChan.c (ReflectClose): Added missing removal of
the now closed channel from the reflection map. Before we could
crash the system by invoking 'chan postevent' on a closed
reflected channel, dereferencing the dangling pointer in the
map.
* tests/ioCmd.test (iocmd-31.8): Testcase for the above.
Diffstat (limited to 'generic/tclIORChan.c')
-rw-r--r-- | generic/tclIORChan.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 94950e7..905a773 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIORChan.c,v 1.28 2008/02/26 21:50:52 jenglish Exp $ + * RCS: @(#) $Id: tclIORChan.c,v 1.28.2.1 2008/04/04 16:45:50 andreas_kupries Exp $ */ #include <tclInt.h> @@ -1010,6 +1010,8 @@ ReflectClose( ReflectedChannel *rcPtr = (ReflectedChannel *) clientData; int result; /* Result code for 'close' */ Tcl_Obj *resObj; /* Result data for 'close' */ + ReflectedChannelMap* rcmPtr; /* Map of reflected channels with handlers in this interp */ + Tcl_HashEntry* hPtr; /* Entry in the above map */ if (interp == NULL) { /* @@ -1090,6 +1092,18 @@ ReflectClose( Tcl_DecrRefCount(resObj); /* Remove reference we held from the * invoke */ + + /* + * Remove the channel from the map before releasing the memory, to + * prevent future accesses (like by 'postevent') from finding and + * dereferencing a dangling pointer. + */ + + rcmPtr = GetReflectedChannelMap (interp); + hPtr = Tcl_FindHashEntry (&rcmPtr->map, + Tcl_GetChannelName (rcPtr->chan)); + Tcl_DeleteHashEntry (hPtr); + FreeReflectedChannel(rcPtr); #ifdef TCL_THREADS } |