Tcl Source Code

Artifact [6524d074ad]
Login

Artifact 6524d074ad5737e1f1ee4d644a81af21e342d347:

Attachment "tcl85.diff-wu" to ticket [2407783fff] added by andreas_kupries 2008-12-11 07:37:08.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.3975.2.134
diff -w -u -r1.3975.2.134 ChangeLog
--- ChangeLog	10 Dec 2008 19:03:58 -0000	1.3975.2.134
+++ ChangeLog	11 Dec 2008 00:33:28 -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.137.2.9
diff -w -u -r1.137.2.9 tclIO.c
--- generic/tclIO.c	2 Dec 2008 18:23:51 -0000	1.137.2.9
+++ generic/tclIO.c	11 Dec 2008 00:33:29 -0000
@@ -220,6 +220,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)) || \
@@ -10613,7 +10617,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((ClientData) statePtr);
     copyPtr->typePtr = &tclChannelType;
 }
@@ -10641,6 +10648,7 @@
     register Tcl_Obj *objPtr)	/* The object to convert. */
 {
     ChannelState *statePtr;
+    Interp       *interpPtr;
 
     if (objPtr->typePtr == &tclChannelType) {
 	/*
@@ -10648,11 +10656,16 @@
 	 * Ensure consistency checks are done.
 	 */
 	statePtr = GET_CHANNELSTATE(objPtr);
+	interpPtr = GET_CHANNELINTERP(objPtr);
 	if (statePtr->flags & (CHANNEL_TAINTED|CHANNEL_CLOSED)) {
 	    ResetFlag(statePtr, CHANNEL_TAINTED);
 	    Tcl_Release((ClientData) statePtr);
 	    UpdateStringOfChannel(objPtr);
 	    objPtr->typePtr = NULL;
+	} else if (interpPtr != (Interp*) interp) {
+	    Tcl_Release((ClientData) statePtr);
+	    UpdateStringOfChannel(objPtr);
+	    objPtr->typePtr = NULL;
 	}
     }
     if (objPtr->typePtr != &tclChannelType) {
@@ -10675,6 +10688,7 @@
 	statePtr = ((Channel *)chan)->state;
 	Tcl_Preserve((ClientData) 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.80.2.12
diff -w -u -r1.80.2.12 io.test
--- tests/io.test	20 Jun 2008 19:23:26 -0000	1.80.2.12
+++ tests/io.test	11 Dec 2008 00:33:29 -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