diff options
author | andreas_kupries <akupries@shaw.ca> | 2008-04-04 16:46:57 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2008-04-04 16:46:57 (GMT) |
commit | bd64b428cf44de3abad33cda014cb21a5252ef79 (patch) | |
tree | 5c53dad0a279bb101e8f30f2530c0f68414f278c /generic | |
parent | 691a1239878ea8dece6135548a490b4d36285fe2 (diff) | |
download | tcl-bd64b428cf44de3abad33cda014cb21a5252ef79.zip tcl-bd64b428cf44de3abad33cda014cb21a5252ef79.tar.gz tcl-bd64b428cf44de3abad33cda014cb21a5252ef79.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')
-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..10d0b2e 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.29 2008/04/04 16:46:57 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 } |