diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2009-12-16 23:31:31 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2009-12-16 23:31:31 (GMT) |
commit | 342c553d632744e239b6e614cf6ecdbe8cf0befd (patch) | |
tree | 975d4feb1bef267978e6693d9d311cf84f92890f /library/safe.tcl | |
parent | a71c14e5ab7004c6ff446303a9c13b2bdcadd57d (diff) | |
download | tcl-342c553d632744e239b6e614cf6ecdbe8cf0befd.zip tcl-342c553d632744e239b6e614cf6ecdbe8cf0befd.tar.gz tcl-342c553d632744e239b6e614cf6ecdbe8cf0befd.tar.bz2 |
Upgrade to Safe Base's handling of [glob] to be more permissive with the
feature set supported, but stricter with path management. It also now has an
error pattern more like the standard [glob] command.
Diffstat (limited to 'library/safe.tcl')
-rw-r--r-- | library/safe.tcl | 102 |
1 files changed, 77 insertions, 25 deletions
diff --git a/library/safe.tcl b/library/safe.tcl index 52b539b..3b9ee19 100644 --- a/library/safe.tcl +++ b/library/safe.tcl @@ -12,7 +12,7 @@ # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: safe.tcl,v 1.16.4.3 2009/12/09 22:34:20 andreas_kupries Exp $ +# RCS: @(#) $Id: safe.tcl,v 1.16.4.4 2009/12/16 23:31:31 dkf Exp $ # # The implementation is based on namespaces. These naming conventions are @@ -655,30 +655,43 @@ proc ::safe::AliasGlob {slave args} { Log $slave "GLOB ! $args" NOTICE set cmd {} set at 0 + array set got { + -directory 0 + -nocomplain 0 + -join 0 + -tails 0 + -- 0 + } + + if {$::tcl_platform(platform) eq "windows"} { + set dirPartRE {^(.*)[\\/]} + } else { + set dirPartRE {^(.*)/} + } set dir {} set virtualdir {} while {$at < [llength $args]} { switch -glob -- [set opt [lindex $args $at]] { - -nocomplain - - -join { + -nocomplain - -- - -join - -tails { lappend cmd $opt + set got($opt) 1 incr at } - -directory { - set virtualdir [lindex $args [incr at]] - # Get the real path from the virtual one and check that the - # path is in the access path of that slave. - try { - set dir [TranslatePath $slave $virtualdir] - DirInAccessPath $slave $dir - } on error msg { - Log $slave $msg - return -code error "permission denied" + -types - -type { + lappend cmd -types [lindex $args [incr at]] + incr at + } + -directory { + if {$got($opt)} { + return -code error \ + {"-directory" cannot be used with "-path"} } - lappend cmd -directory $dir + set got($opt) 1 + set virtualdir [lindex $args [incr at]] incr at + lappend cmd -directory $dir } pkgIndex.tcl { # Oops, this is globbing a subdirectory in regular package @@ -692,22 +705,58 @@ proc ::safe::AliasGlob {slave args} { return -code error "Safe base rejecting glob option '$opt'" } default { - if {[regexp {(.*)[\\/]} $opt -> thedir]} { - try { - DirInAccessPath $slave [TranslatePath $slave $thedir] - } on error msg { - Log $slave $msg - return -code error "permission denied" - } - } - lappend cmd $opt - incr at + break + } + } + if {$got(--) || $got(-join)} break + } + + # Get the real path from the virtual one and check that the path is in the + # access path of that slave. Done after basic argument processing so that + # we know if -nocomplain is set. + if {$got(-directory)} { + if {[catch { + set dir [TranslatePath $slave $virtualdir] + DirInAccessPath $slave $dir + } msg]} { + Log $slave $msg + if {!$got(-nocomplain)} { + return -code error "permission denied" + } else { + return } } } + # Apply the -join semantics ourselves + if {$got(-join)} { + set args [lreplace $args $at end [join [lrange $args $at end] "/"]] + } + + # Process remaining pattern arguments + set firstPattern [llength $cmd] + while {$at < [llength $args]} { + set opt [lindex $args $at] + incr at + if {[regexp $dirPartRE $opt -> thedir] && [catch { + set thedir [file join $virtualdir $thedir] + DirInAccessPath $slave [TranslatePath $slave $thedir] + } msg]} { + Log $slave $msg + if {$got(-nocomplain)} { + continue + } else { + return -code error "permission denied" + } + } + lappend cmd $opt + } + Log $slave "GLOB = $cmd" NOTICE + if {$got(-nocomplain) && [llength $cmd] eq $firstPattern} { + return + } if {[catch { ::interp invokehidden $slave glob {*}$cmd } msg]} { @@ -719,8 +768,11 @@ proc ::safe::AliasGlob {slave args} { # Translate path back to what the slave should see. set res {} + set l [string length $dir] foreach p $msg { - regsub -- ^$dir $p $virtualdir p + if {[string equal -length $l $dir $p]} { + set p [string replace $p 0 [expr {$l-1}] $virtualdir] + } lappend res $p } |