Tcl Source Code

View Ticket
Login
Ticket UUID: 956063
Title: [file dirname] broken
Type: Bug Version: obsolete: 8.5a1
Submitter: dgp Created on: 2004-05-18 16:47:51
Subsystem: 37. File System Assigned To: kennykb
Priority: 8 Severity:
Status: Closed Last Modified: 2004-05-19 23:58:09
Resolution: Fixed Closed By: vincentdarley
    Closed on: 2004-05-19 16:58:09
Description:
% info patch
8.5a1
% file mkdir foo
% set f [open [file join foo bar.tcl] w]
file3
% puts $f {
puts SOURCE:[info script]
puts NORMALIZED:[file normalize [info script]]
puts HOME:[file dirname [file normalize [info script]]]
}
% close $f
% source [file join foo bar.tcl]
SOURCE:foo/bar.tcl
NORMALIZED:/home/dgp/foo/bar.tcl
HOME:/home/dgp

Of course, I expect to see

HOME:/home/dgp/foo

This is a very common way to set up
paths relative to a script being 
[source]d.  It must be reliably correct.
User Comments: vincentdarley added on 2004-05-19 23:58:09:
Logged In: YES 
user_id=32170

Checked out both patches, and I think on balance I prefer
mine-- that code in Tcl_FSJoinPath was designed to handle
the case that dgp's patch is excluding, which I think just
removes a possible efficiency benefit.

vincentdarley added on 2004-05-19 22:43:08:

File Added - 87657: filedirname.diff

Logged In: YES 
user_id=32170

I can get the problem to occur on windows, quite simply:

test cmdAH-8.46 {Tcl_FileObjCmd: dirname} {
    set f [file normalize [info nameof]]
    file exists $f
    set res1 [file dirname [file join $f foo/bar]]
    set res2 [file dirname "${f}/foo/bar"]
    if {$res1 eq $res2} {
set res "ok"
    } else {
        set res "file dirname problem, $res1, $res2 not equal"
    }
    set res
} {ok}

I've attached an alternative patch which changes the
behaviour of TclPathPart.

For what it's worth, TclPathPart's optimization is what
really introduced the bug so the obvious place to me to fix
it is there.  However, I'm interested to look at your patch
and see how you fixed it in a different way (just no time
today).

dgp added on 2004-05-19 04:57:09:

File Added - 87578: 956063.patch

Logged In: YES 
user_id=80530


Here's a patch.

Not also that this patch
makes clear why the
failure doesn't show up
on Windows.  The flaw
is in a Unix-only optimization.

Please test.

dgp added on 2004-05-19 04:48:39:
Logged In: YES 
user_id=80530


It appears that the cleanest
place to correct this is within
Tcl_FSJoinPath().  That appears
to be the only place where
TclNewFSPathObj() gets called
with a possibility that addStrRep
might contain separators.

Also, there's already fallback
code there to deal with the
failing case.

dgp added on 2004-05-19 03:22:40:
Logged In: YES 
user_id=80530


However, [file join] calls
Tcl_FSJoinToPath() directly,
and it has no such restriction,
so perhaps the docs are wrong,
or perhaps I don't correctly
understand what a "path segement"
is.

dgp added on 2004-05-19 03:20:54:
Logged In: YES 
user_id=80530


NOTE: Both Tcl_FSJoinPath
and Tcl_FSJoinToPath are
explicitly documented to accept
a list and array, respectively,
of path segments.  It is a bug
to call them with one of those
segments containing a path
separator.

dgp added on 2004-05-19 03:06:03:
Logged In: YES 
user_id=80530


TclPathPart notices when the
PATHFLAGS is not 0
(presumably is TCLPATH_APPENDED)
and based on that assumes that
the cwdPtr is the dirname and
the normPathPtr is the tail.

That would be a safe assumption
if TclNewFSPathObj forbade
path separators in its addStrRep
argument, but it doesn't appear to
do so.

Since these are internal routines,
all would also be ok, if simply
by convention, nothing called
TclNewFSPathObj with a
separator in the addStrRep argument.
However, in this test script, the
call:

TclNewFSPathObj (dirPtr=0x8071070, addStrRep=0x8081b30
"foo/bar.tcl",
    len=11) at ../unix/../generic/tclPathObj.c:109

takes place.

I think the proper fix here requires
a more precise spec. of what
assumptions different PATHFLAGS
values impose, and a careful audit
the the relevant routines preserve
those specs.

vincentdarley added on 2004-05-19 00:59:02:
Logged In: YES 
user_id=32170

I suspect TclPathPart in tclPathObj.c, for the special case
of a path which is the result of a [file join].  Don't have
time to look into it at the moment, but that's probably the
culprit.

dgp added on 2004-05-19 00:00:39:
Logged In: YES 
user_id=80530

change to

set path [file normalize [info script]]
puts HOME:[file dirname [string range " $path" 1 end]]

and that works, so something is broken
in the cached normalized path value.
Forcing the shimmer fixes it.

dgp added on 2004-05-18 23:57:14:
Logged In: YES 
user_id=80530


Bug appears to be on
Unix systems only.  Works
correctly on Windows.

Suspect errors in TclpObjNormalizePath()
or related code in the unix/ source.

dgp added on 2004-05-18 23:48:39:
Logged In: YES 
user_id=80530

BTW, this bug appears to be
new in Tcl 8.5.  Tcl 8.4.6
behaves correctly on this
test.

Attachments: