summaryrefslogtreecommitdiffstats
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/package.tcl10
-rw-r--r--library/safe.tcl74
-rw-r--r--library/tm.tcl11
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