summaryrefslogtreecommitdiffstats
path: root/generic/tclIORChan.c
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2008-04-04 16:45:48 (GMT)
committerandreas_kupries <akupries@shaw.ca>2008-04-04 16:45:48 (GMT)
commitdd13549c2381c348b6536501d389e513a6082f5d (patch)
treedf824fb86004bdab22bfe820fe7088ec3497714d /generic/tclIORChan.c
parentf22c720323ae972ba91834691c7c0ad1b800d2df (diff)
downloadtcl-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.c16
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
}