diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/package.tcl | 10 | ||||
-rw-r--r-- | library/safe.tcl | 74 | ||||
-rw-r--r-- | library/tm.tcl | 11 |
3 files changed, 62 insertions, 33 deletions
diff --git a/library/package.tcl b/library/package.tcl index 6c87ec1..bf3e926 100644 --- a/library/package.tcl +++ b/library/package.tcl @@ -479,9 +479,12 @@ proc tclPkgUnknown {name args} { } set tclSeenPath($dir) 1 - # we can't use glob in safe interps, so enclose the following in a - # catch statement, where we get the pkgIndex files out of the - # subdirectories + # Get the pkgIndex.tcl files in subdirectories of auto_path directories. + # - Safe Base interpreters have a restricted "glob" command that + # works in this case. + # - The "catch" was essential when there was no safe glob and every + # call in a safe interp failed; it is retained only for corner + # cases in which the eventual call to glob returns an error. catch { foreach file [glob -directory $dir -join -nocomplain \ * pkgIndex.tcl] { @@ -593,6 +596,7 @@ proc tcl::MacOSXPkgUnknown {original name args} { set tclSeenPath($dir) 1 # get the pkgIndex files out of the subdirectories + # Safe interpreters do not use tcl::MacOSXPkgUnknown - see init.tcl. foreach file [glob -directory $dir -join -nocomplain \ * Resources Scripts pkgIndex.tcl] { set dir [file dirname $file] diff --git a/library/safe.tcl b/library/safe.tcl index 46f0c64..b73aad5 100644 --- a/library/safe.tcl +++ b/library/safe.tcl @@ -483,14 +483,6 @@ proc ::safe::InterpSetConfig {slave access_path staticsok nestedok deletehook au lappend slave_tm_rel $relpath } } - foreach sub [glob -nocomplain -directory $dir -type d *] { - lappend slave_tm_roots [file normalize $sub] [dict get $slave_tm_roots $dir] - set lenny [string length [dict get $slave_tm_roots $dir]] - set relpath [string range [file normalize $sub] $lenny+1 end] - if {$relpath ni $slave_tm_rel} { - lappend slave_tm_rel $relpath - } - } } set firstpass 0 } @@ -897,17 +889,6 @@ proc ::safe::AliasGlob {slave args} { set virtualdir [lindex $args [incr at]] incr at } - pkgIndex.tcl { - if {$AutoPathSync} { - # Oops, this is globbing a subdirectory in regular package - # search. That is not wanted. Abort, handler does catch - # already (because glob was not defined before). See - # package.tcl, lines 484ff in tclPkgUnknown. - return -code error "unknown command glob" - } else { - break - } - } -* { Log $slave "Safe base rejecting glob option '$opt'" return -code error "Safe base rejecting glob option '$opt'" @@ -932,7 +913,18 @@ proc ::safe::AliasGlob {slave args} { if {$got(-nocomplain)} return return -code error "permission denied" } - lappend cmd -directory $dir + if {$got(--)} { + set cmd [linsert $cmd end-1 -directory $dir] + } else { + lappend cmd -directory $dir + } + } else { + # The code after this "if ... else" block would conspire to return with + # no results in this case, if it were allowed to proceed. Instead, + # return now and reduce the number of cases to be considered later. + Log $slave {option -directory must be supplied} + if {$got(-nocomplain)} return + return -code error "permission denied" } # Apply the -join semantics ourselves (hence -join not copied to $cmd) @@ -940,16 +932,21 @@ proc ::safe::AliasGlob {slave args} { set args [lreplace $args $at end [join [lrange $args $at end] "/"]] } - # Process remaining pattern arguments + # Process the pattern arguments. If we've done a join there is only one + # pattern argument. + set firstPattern [llength $cmd] foreach opt [lrange $args $at end] { if {![regexp $dirPartRE $opt -> thedir thefile]} { set thedir . - } elseif {[string match ~* $thedir]} { - set thedir ./$thedir + # The *.tm search comes here. } - if {$thedir eq "*" && - ($thefile eq "pkgIndex.tcl" || $thefile eq "*.tm")} { + # "Special" treatment for (joined) argument {*/pkgIndex.tcl}. + # Do the expansion of "*" here, and filter out any directories that are + # not in the access path. The outcome is to lappend to cmd a path of + # the form $virtualdir/subdir/pkgIndex.tcl for each subdirectory subdir, + # after removing any subdir that are not in the access path. + if {($thedir eq "*") && ($thefile eq "pkgIndex.tcl")} { set mapped 0 foreach d [glob -directory [TranslatePath $slave $virtualdir] \ -types d -tails *] { @@ -961,7 +958,25 @@ proc ::safe::AliasGlob {slave args} { } } if {$mapped} continue + # Don't [continue] if */pkgIndex.tcl has no matches in the access + # path. The pattern will now receive the same treatment as a + # "non-special" pattern (and will fail because it includes a "*" in + # the directory name). } + # Any directory pattern that is not an exact (i.e. non-glob) match to a + # directory in the access path will be rejected here. + # - Rejections include any directory pattern that has glob matching + # patterns "*", "?", backslashes, braces or square brackets, (UNLESS + # it corresponds to a genuine directory name AND that directory is in + # the access path). + # - The only "special matching characters" that remain in patterns for + # processing by glob are in the filename tail. + # - [file join $anything ~${foo}] is ~${foo}, which is not an exact + # match to any directory in the access path. Hence directory patterns + # that begin with "~" are rejected here. Tests safe-16.[5-8] check + # that "file join" remains as required and does not expand ~${foo}. + # - Bug [3529949] relates to unwanted expansion of ~${foo} and this is + # how the present code avoids the bug. All tests safe-16.* relate. try { DirInAccessPath $slave [TranslatePath $slave \ [file join $virtualdir $thedir]] @@ -979,8 +994,17 @@ proc ::safe::AliasGlob {slave args} { return } try { + # >>>>>>>>>> HERE'S THE CALL TO SAFE INTERP GLOB <<<<<<<<<< + # - Pattern arguments added to cmd have NOT been translated from tokens. + # Only the virtualdir is translated (to dir). + # - In the pkgIndex.tcl case, there is no "*" in the pattern arguments, + # which are a list of names each with tail pkgIndex.tcl. The purpose + # of the call to glob is to remove the names for which the file does + # not exist. set entries [::interp invokehidden $slave glob {*}$cmd] } on error msg { + # This is the only place that a call with -nocomplain and no invalid + # "dash-options" can return an error. Log $slave $msg return -code error "script error" } diff --git a/library/tm.tcl b/library/tm.tcl index 0ed3f1a..c60084c 100644 --- a/library/tm.tcl +++ b/library/tm.tcl @@ -212,11 +212,12 @@ proc ::tcl::tm::UnknownHandler {original name args} { } set strip [llength [file split $path]] - # We can't use glob in safe interps, so enclose the following in a - # catch statement, where we get the module files out of the - # subdirectories. In other words, Tcl Modules are not-functional - # in such an interpreter. This is the same as for the command - # "tclPkgUnknown", i.e. the search for regular packages. + # Get the module files out of the subdirectories. + # - Safe Base interpreters have a restricted "glob" command that + # works in this case. + # - The "catch" was essential when there was no safe glob and every + # call in a safe interp failed; it is retained only for corner + # cases in which the eventual call to glob returns an error. catch { # We always look for _all_ possible modules in the current |