Index: generic/tclPathObj.c ================================================================== --- generic/tclPathObj.c +++ generic/tclPathObj.c @@ -1275,10 +1275,19 @@ { FsPath *fsPathPtr; Tcl_Obj *pathPtr; const char *p; int state = 0, count = 0; + + /* if dirPtr is already tclFsPathType, its string representation + * may not be canonical. Try to use its normPathPtr in this case. + */ + if ( (dirPtr->typePtr == &tclFsPathType) + && (PATHOBJ(dirPtr)->cwdPtr == NULL) + && (PATHOBJ(dirPtr)->normPathPtr != NULL) ) { + dirPtr = PATHOBJ(dirPtr)->normPathPtr; + } /* [Bug 2806250] - this is only a partial solution of the problem. * The PATHFLAGS != 0 representation assumes in many places that * the "tail" part stored in the normPathPtr field is itself a * relative path. Strings that begin with "~" are not relative paths, Index: tests/fileSystem.test ================================================================== --- tests/fileSystem.test +++ tests/fileSystem.test @@ -365,10 +365,20 @@ testPathEqual [file norm /../..] [file norm /] } ok test filesystem-1.51.1 {file normalisation .. beyond root (Bug 1379287)} { testPathEqual [file norm /../../] [file norm /] } ok +test filesystem-1.52 {bug f9f390d0fa: file join where strep is not canonical} -body { + set x //foo + file normalize $x + file join $x bar +} -result /foo/bar +test filesystem-1.52.1 {bug f9f390d0fa: file join where strep is not canonical} -body { + set x //foo + file normalize $x + file join $x +} -result /foo test filesystem-2.0 {new native path} {unix} { foreach f [lsort [glob -nocomplain /usr/bin/c*]] { catch {file readlink $f} }