diff options
-rw-r--r-- | nshelper.tcl | 14 | ||||
-rw-r--r-- | tests/namespace.test | 23 |
2 files changed, 35 insertions, 2 deletions
diff --git a/nshelper.tcl b/nshelper.tcl index d0cb35a..a31b7c0 100644 --- a/nshelper.tcl +++ b/nshelper.tcl @@ -66,7 +66,19 @@ proc {namespace import} {args} { if {[namespace qualifiers $cmd] eq $current} { return -code error "import pattern \"$pattern\" tries to import from namespace \"$current\" into itself" } - alias ${current}::[namespace tail $cmd] $cmd + # What if this alias would create a loop? + # follow the target alias chain to see if we are creating a loop + set newcmd ${current}::[namespace tail $cmd] + + set alias $cmd + while {[exists -alias $alias]} { + set alias [info alias $alias] + if {$alias eq $newcmd} { + return -code error "import pattern \"$pattern\" would create a loop" + } + } + + alias $newcmd $cmd } } } diff --git a/tests/namespace.test b/tests/namespace.test index 090fcf0..6c36672 100644 --- a/tests/namespace.test +++ b/tests/namespace.test @@ -482,9 +482,30 @@ test namespace-12.1 {namespace import} { } {a} test namespace-12.2 {namespace import recursive} -body { - namespace import * + namespace eval test_ns_scope1 { + namespace import [namespace current]::* + } } -returnCodes error -match glob -result {import pattern "*" tries to import from namespace "*" into itself} +test namespace-12.3 {namespace import loop} -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*} + foreach cmd [info commands test_ns_*] { rename $cmd "" } |