Attachment "1017299.patch" to
ticket [1017299fff]
added by
dgp
2004-09-10 00:02:33.
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.49
diff -u -r1.49 tclNamesp.c
--- generic/tclNamesp.c 9 Sep 2004 15:44:23 -0000 1.49
+++ generic/tclNamesp.c 9 Sep 2004 16:55:55 -0000
@@ -1273,7 +1273,7 @@
char *cmdName;
register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- Command *cmdPtr, *realCmdPtr;
+ Command *cmdPtr;
ImportRef *refPtr;
Tcl_Command autoCmd, importedCmd;
ImportedCmdData *dataPtr;
@@ -1373,6 +1373,7 @@
* pattern. Check whether it was exported. If it wasn't,
* we ignore it.
*/
+ Tcl_HashEntry *found;
wasExported = 0;
for (i = 0; i < importNsPtr->numExportPatterns; i++) {
@@ -1390,8 +1391,9 @@
* in the current namespace that refers to cmdPtr.
*/
- if ((Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName) == NULL)
- || allowOverwrite) {
+
+ found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
+ if ((found == NULL) || allowOverwrite) {
/*
* Create the imported command and its client data.
* To create the new command in the current namespace,
@@ -1409,25 +1411,30 @@
/*
* Check whether creating the new imported command in the
- * current namespace would create a cycle of imported->real
- * command references that also would destroy an existing
- * "real" command already in the current namespace.
+ * current namespace would create a cycle of imported
+ * command references.
*/
cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
- if (cmdPtr->deleteProc == DeleteImportedCmd) {
- realCmdPtr = (Command *) TclGetOriginalCommand(
- (Tcl_Command) cmdPtr);
- if ((realCmdPtr != NULL)
- && (realCmdPtr->nsPtr == currNsPtr)
- && (Tcl_FindHashEntry(&currNsPtr->cmdTable,
- cmdName) != NULL)) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "import pattern \"", pattern,
- "\" would create a loop containing command \"",
- Tcl_DStringValue(&ds), "\"", (char *) NULL);
- Tcl_DStringFree(&ds);
- return TCL_ERROR;
+ if ((found != NULL)
+ && cmdPtr->deleteProc == DeleteImportedCmd) {
+
+ Command *overwrite = (Command *) Tcl_GetHashValue(found);
+ Command *link = cmdPtr;
+ while (link->deleteProc == DeleteImportedCmd) {
+ ImportedCmdData *dataPtr;
+
+ dataPtr = (ImportedCmdData *) link->objClientData;
+ link = dataPtr->realCmdPtr;
+ if (overwrite == link) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "import pattern \"", pattern,
+ "\" would create a loop containing ",
+ "command \"", Tcl_DStringValue(&ds),
+ "\"", (char *) NULL);
+ Tcl_DStringFree(&ds);
+ return TCL_ERROR;
+ }
}
}
Index: tests/namespace.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/namespace.test,v
retrieving revision 1.35
diff -u -r1.35 namespace.test
--- tests/namespace.test 9 Sep 2004 15:44:23 -0000 1.35
+++ tests/namespace.test 9 Sep 2004 16:55:57 -0000
@@ -244,6 +244,50 @@
[test_ns_export::cmd1 j k l]
} {{cmd1: a b c} {cmd1: d e f} {} ::test_ns_export::cmd1 ::test_ns_export::cmd1 {new1: g h i} {new1: j k l}}
+test namespace-9.8 {Tcl_Import: Bug 1017299} -setup {
+ namespace eval one {
+ namespace export cmd
+ proc cmd {} {}
+ }
+ namespace eval two {
+ namespace export cmd
+ proc other args {}
+ }
+ namespace eval two \
+ [list namespace import [namespace current]::one::cmd]
+ namespace eval three \
+ [list namespace import [namespace current]::two::cmd]
+ namespace eval three {
+ rename cmd other
+ namespace export other
+ }
+} -body {
+ namespace eval two [list namespace import -force \
+ [namespace current]::three::other]
+ namespace origin two::other
+} -cleanup {
+ namespace delete one two three
+} -match glob -result *::one::cmd
+
+test namespace-9.9 {Tcl_Import: Bug 1017299} -setup {
+ namespace eval one {
+ namespace export cmd
+ proc cmd {} {}
+ }
+ namespace eval two namespace export cmd
+ namespace eval two \
+ [list namespace import [namespace current]::one::cmd]
+ namespace eval three namespace export cmd
+ namespace eval three \
+ [list namespace import [namespace current]::two::cmd]
+} -body {
+ namespace eval two [list namespace import -force \
+ [namespace current]::three::cmd]
+ namespace origin two::cmd
+} -cleanup {
+ namespace delete one two three
+} -returnCodes error -match glob -result {import pattern * would create a loop*}
+
test namespace-10.1 {Tcl_ForgetImport, check for valid namespaces} {
catch {namespace delete {expand}[namespace children :: test_ns_*]}
list [catch {namespace forget xyzzy::*} msg] $msg