Ticket UUID: | 2511011 | |||
Title: | [glob] can return non-existing filenames | |||
Type: | RFE | Version: | None | |
Submitter: | mpc_janssen | Created on: | 2009-01-15 19:31:03 | |
Subsystem: | 36. Pathname Management | Assigned To: | dgp | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Open | Last Modified: | 2018-04-09 15:29:35 | |
Resolution: | None | Closed By: | nobody | |
Closed on: | ||||
Description: |
glob doesn't escape filenames starting with ~. This means glob by default can return filenames that 1) don't exists (annoying) or even point to a different spot all together (a user directory for instance, which is outright dangerous). For example: create a file name "~test" % foreach file [glob *] { if {![file exists $file]} {puts "huh $file doesn't exists"}} huh ~test doesn't exists % info pa 8.5.4 Interactive session above was with Tcl 8.5.4. Dangerous situations can occur if a filename matches a valid user directory (~ for instance) and results of glob are used in recursive delete operations (which would lead to removal of the users home dir in this case) It seems that me that glob should properly escape ~ as "./~test". | |||
User Comments: |
sebres added on 2018-04-09 15:29:35:
I think either we should "fix" this or provide a fix for `filename-11.42`, because of annoying sporadic test fails within: if the test-suite runs in the temp-folder it can contains some files like `$::env(tmp)/~DF670D65B85835F8E2.TMP` (e. g. very often on windows platform). So this test-case will always fail there, because $res never equal `[glob *]` there. Additionally, I believe `[glob *]` is basically nothing other as `[glob -tails -directory [pwd] *]`, because both returns relative paths. But ATM both do not real `file tail` (at least in sense of Tcl's file tail), so e. g. in case of filename-11.42 it works wrong - you'll get `~DF67.TMP` instead of `./~DF67.TMP`. BTW, it is very weird as it's currently implemented. For example this fully legal simple code will fail, if contain such files (with "User DF67.TMP doesn't exist"): foreach fn [glob -tails -directory [pwd] *] { puts "touch $fn" close [open $fn r] } But this one (quasi doing the same) runs successfully: set res [list] foreach f [glob -dir [pwd] -types f *] { lappend res [file tail $f] } foreach fn $res { puts "touch $fn" close [open $fn r] } I'm for fixing glob for both cases (`glob *` as well as `glob -dir [pwd] -tails *`). Because IMHO it must return correct relative path! dgp added on 2009-08-19 02:54:43: data_type - 360894 tests filesystem-9.7,8,9 are present to guarantee that the behavior reported here continues unchanged. It may be annoying and stupid, but it is intentional. Not a bug. Shifting this report over the Feature Request tracker. dgp added on 2009-08-15 02:28:26: On the other hand, test filename-11.42, which was put in place for the 8.4.0 release explicitly tests that the elements returned by [glob *] match what would be produced by [file tail], which fails precisely on the sort of filenames examined here. dgp added on 2009-08-14 23:17:18: Comments in the routine TclFSMakePathRelative() indicate an awareness of this issue, and an intentional discarding of cached intreps so that the ~foo name can be re-interpreted later without contradiction. The recorded justification is that "this is how glob is currently defined". This is looking like RFE/TIP territory. dgp added on 2009-08-14 22:18:09: The command [tk::dialog::file::JoinFile] is an example of needing to work around this issue. dgp added on 2009-08-14 05:22:51: At least this example of the problem seems to filter down to a flaw in the TclFSMakePathRelative() which is failing to, um, make the path relative. :) dgp added on 2009-08-14 00:37:03: Note that with VFS, this problem can be more general than ~ expansion. Any time the tail of an absolute filename is recognized on its own also as a different absolute filename, there's going to be confusion that the pathnames returned by [glob] do not point back the the same files whose existence [glob] is acting upon. Need to dig in to be sure, but it seems the right solution is some checking within [glob] that the paths it returns that it expects to be relative are in fact relative, and applying some fix (following the ./ prefixing example) to correct any that are not. Even that will leave some difficulties, if a relative path is retrieved from [glob] and stored, and then a later mount of a filesystem converts that stored path from relative to absolute. I think that level of difficulty cannot be avoided given the dynamic view of the filesystem Tcl exposes. Any paths meant to be kept around for any length of time at all need to be in absolute form. dgp added on 2009-08-14 00:30:12: IP - Comment Removed: 129.6.88.51 dgp added on 2009-08-13 04:40:10: Reported again within 2834453. dkf added on 2009-02-24 17:40:23: The backslashes will have no effect; they're processed at an entirely different level of Tcl. The only question is what the contract for [glob] in this situation should actually be. (Note that it is pretty clear what [glob -tails] should be doing; it's when that option is not specified that I'm not sure what should be happening.) Also, if things are changed then are we going to be adversely impacting uses of [glob]? That's also important. (Well, there's also the bizarre bugs in [file tail], but they probably should be their own Bug...) [email protected] added on 2009-02-24 06:20:14: Yes expansion of ~ is the culprit in this scenario. (most of?) Tcl's file commands interpret ~ as a home directory. If [glob] does not escape ~ in a filename it returns it is a bug in [glob]. Rewriting glob results to escape ~ is not an option. The contract of [glob] specifies it returns filenames. If you try to argue that automatic ~ expansion is a bad thing, I am likely to agree (it's a UNIX-ism for one) but that's unfixable without breaking backward compatibility. cwjolly added on 2009-02-24 06:00:39: Seems to me since you do create the file and glob finds it that it is not a bug with glob but rather with file exists. Its the "file exists" command that does not see the file. Since tcl supports ~ expansion it is likely that the home directory is being appended to the remainder of the filename and sois not found. e.g. if the home directory == /home/chuck then ~test is transformed to /home/chucktest prior to checking for existance. I tried the following using 8.5.0 and it points to the ~ expansion as the culprit for a number of path associated commands. At the bottom it would appear that as suggested above that appending ./ to each file will allow file exists (and other commands to succeed) : % info pa 8.5.0 % package require fileutil 1.13.5 % fileutil::touch ~test user "test" doesn't exist % fileutil::touch \~test user "test" doesn't exist % exec touch ~test % glob ~* user "*" doesn't exist % glob *test ~test mytest % file exists ~test 0 % file normalize ~test user "test" doesn't exist % file normalize \~test user "test" doesn't exist % file exists [file normalize ~test] user "test" doesn't exist % file exists [file normalize ./~test ] 1 dgp added on 2009-02-05 05:42:22: There's a related regression in [file tail]: % set files [glob *oo] ~boo ~foo % set files2 [glob -directory [pwd] *oo] /home/dgp/cvs/tcl8.4/unix/~boo /home/dgp/cvs/tcl8.4/unix/~foo % file tail [lindex $files2 0] ./~boo % info patch 8.4.19 % set files [glob *oo] ~foo ~boo % set files2 [glob -directory [pwd] *oo] /home/dgp/cvs/tcl8.5/unix/~foo /home/dgp/cvs/tcl8.5/unix/~boo % file tail [lindex $files2 0] ~foo % file tail /home/dgp/cvs/tcl8.5/unix/~foo ./~foo % info patch 8.5.6 The symptoms point to inconsistent handling of values of the "path" Tcl_ObjType depending on the details of the intrep. Same string ought to produce same results, but do not. |