Tcl Source Code

Artifact [aa0c3e7e4a]
Login

Artifact aa0c3e7e4a403d152013e0564968c988301bb13f:

Attachment "tcl86.diff-wu" to ticket [2407783fff] added by andreas_kupries 2008-12-11 07:37:52.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.4397
diff -w -u -r1.4397 ChangeLog
--- ChangeLog	10 Dec 2008 19:00:53 -0000	1.4397
+++ ChangeLog	11 Dec 2008 00:33:31 -0000
@@ -1,3 +1,12 @@
+2008-12-10  Andreas Kupries   <[email protected]>
+
+	* generic/tclIO.c (SetChannelFromAny and related): Modified the
+	internal representation of the tclChannelType to contain not only
+	the ChannelState pointer, but also a reference to the interpreter
+	it was made in. Invalidate and recompute the internal
+	representation when it is used in a different interpreter
+	(Like cmdName intrep's). [Bug 2407783].
+
 2008-12-10  Kevin B. Kenny  <[email protected]>
 
 	* library/tzdata/*: Update from Olson's tzdata2008i.
Index: generic/tclIO.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIO.c,v
retrieving revision 1.153
diff -w -u -r1.153 tclIO.c
--- generic/tclIO.c	9 Dec 2008 20:16:29 -0000	1.153
+++ generic/tclIO.c	11 Dec 2008 00:33:34 -0000
@@ -222,6 +222,10 @@
     ((ChannelState *) (objPtr)->internalRep.otherValuePtr)
 #define SET_CHANNELSTATE(objPtr, storePtr) \
     ((objPtr)->internalRep.otherValuePtr = (void *) (storePtr))
+#define GET_CHANNELINTERP(objPtr) \
+    ((Interp *) (objPtr)->internalRep.twoPtrValue.ptr2)
+#define SET_CHANNELINTERP(objPtr, storePtr) \
+    ((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr))
 
 #define BUSY_STATE(st,fl) \
      ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \
@@ -10612,8 +10616,10 @@
 				 * currently have an internal rep.*/
 {
     ChannelState *statePtr = GET_CHANNELSTATE(srcPtr);
+    Interp       *interpPtr = GET_CHANNELINTERP(srcPtr);
 
     SET_CHANNELSTATE(copyPtr, statePtr);
+    SET_CHANNELINTERP(copyPtr, interpPtr);
     Tcl_Preserve(statePtr);
     copyPtr->typePtr = &tclChannelType;
 }
@@ -10641,6 +10647,7 @@
     register Tcl_Obj *objPtr)	/* The object to convert. */
 {
     ChannelState *statePtr;
+    Interp       *interpPtr;
 
     if (objPtr->typePtr == &tclChannelType) {
 	/*
@@ -10649,11 +10656,16 @@
 	 */
 
 	statePtr = GET_CHANNELSTATE(objPtr);
+	interpPtr = GET_CHANNELINTERP(objPtr);
 	if (GotFlag(statePtr, CHANNEL_TAINTED|CHANNEL_CLOSED)) {
 	    ResetFlag(statePtr, CHANNEL_TAINTED);
 	    Tcl_Release(statePtr);
 	    UpdateStringOfChannel(objPtr);
 	    objPtr->typePtr = NULL;
+	} else if (interpPtr != (Interp*) interp) {
+	    Tcl_Release(statePtr);
+	    UpdateStringOfChannel(objPtr);
+	    objPtr->typePtr = NULL;
 	}
     }
     if (objPtr->typePtr != &tclChannelType) {
@@ -10677,6 +10689,7 @@
 	statePtr = ((Channel *) chan)->state;
 	Tcl_Preserve(statePtr);
 	SET_CHANNELSTATE(objPtr, statePtr);
+	SET_CHANNELINTERP(objPtr, interp);
 	objPtr->typePtr = &tclChannelType;
     }
     return TCL_OK;
Index: tests/io.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/io.test,v
retrieving revision 1.91
diff -w -u -r1.91 io.test
--- tests/io.test	20 Jun 2008 20:48:49 -0000	1.91
+++ tests/io.test	11 Dec 2008 00:33:35 -0000
@@ -7695,6 +7695,16 @@
     catch {close [lreplace [list a] 0 end]}
 } {1}
 
+test io-73.2 {channel Tcl_Obj SetChannelFromAny, bug 2407783} {} {
+    # Invalidate intrep of 'channel' Tcl_Obj when transiting between interpreters.
+    interp create foo
+    set f [open [info script] r]
+    seek $f 0
+    set code [catch {interp eval foo [list seek $f 0]} msg]
+    # The string map converts the changing channel handle to a fixed string
+    list $code [string map [list $f @@] $msg]
+} {1 {can not find channel named "@@"}}
+
 # ### ### ### ######### ######### #########
 
 # cleanup