Ticket UUID: | 1999176 | |||
Title: | glob can cause crash on windows Tcl8.5.2 | |||
Type: | Bug | Version: | obsolete: 8.5.2 | |
Submitter: | nobody | Created on: | 2008-06-20 22:22:55 | |
Subsystem: | 36. Pathname Management | Assigned To: | dgp | |
Priority: | 9 Immediate | Severity: | ||
Status: | Closed | Last Modified: | 2008-06-30 02:39:44 | |
Resolution: | Fixed | Closed By: | dgp | |
Closed on: | 2008-06-29 19:39:44 | |||
Description: |
This glob has crashed my windows on with Tcl8.5.2 glob -nocomplain -directory {} anything Artur [email protected] | |||
User Comments: |
dgp added on 2008-06-30 02:09:51:
Logged In: YES user_id=80530 Originator: NO leak plugged for 8.5.3 and 8.6a2. dgp added on 2008-06-30 02:01:02: Logged In: YES user_id=80530 Originator: NO The trouble is the if () {} else {} on lines 1970 - 1994. With the recent changes, the empty string path actually needs to take both branches, so the logic needs a revision. dgp added on 2008-06-30 01:36:05: Logged In: YES user_id=80530 Originator: NO pointsman reports that commenting out line 1910 of Revision 1.66.2.3 of tclPathObj.c plugs the leak. This indicates that somehow refCounting is broken, but I'm not yet able to sort it out. I think it has something to do with not accounting for the strange Tcl_FSGetCwd() interface that increments refcount for the caller. pointsman added on 2008-06-29 23:37:51: Logged In: YES user_id=13222 Originator: NO Can't attach (not my bug), here's the valgrind output: ==2077== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 105 from 3) ==2077== malloc/free: in use at exit: 218 bytes in 8 blocks. ==2077== malloc/free: 35,978 allocs, 35,970 frees, 2,582,181 bytes allocated. ==2077== For counts of detected errors, rerun with: -v ==2077== searching for pointers to 8 not-freed blocks. ==2077== checked 110,236 bytes. ==2077== ==2077== 218 (24 direct, 194 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2 ==2077== at 0x4019925: malloc (m_replacemalloc/vg_replace_malloc.c:207) ==2077== by 0x404038D: TclpAlloc (/home/rolf/tcltk/tcl8.5.3/generic/tclAlloc.c:706) ==2077== by 0x404A87D: Tcl_Alloc (/home/rolf/tcltk/tcl8.5.3/generic/tclCkalloc.c:1019) ==2077== by 0x40EB07C: Tcl_NewStringObj (/home/rolf/tcltk/tcl8.5.3/generic/tclStringObj.c:210) ==2077== by 0x40D9CE6: TclSubstTokens (/home/rolf/tcltk/tcl8.5.3/generic/tclParse.c:2252) ==2077== by 0x4044BDC: TclEvalEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4191) ==2077== by 0x404479F: Tcl_EvalEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4002) ==2077== by 0x40456F9: TclEvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4674) ==2077== by 0x404542A: Tcl_EvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4555) ==2077== by 0x40E428C: Tcl_UplevelObjCmd (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:911) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4094C10: TclExecuteByteCode (/home/rolf/tcltk/tcl8.5.3/generic/tclExecute.c:2327) ==2077== by 0x40E5062: TclObjInterpProcCore (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:1721) ==2077== by 0x40E4FBC: TclObjInterpProc (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:1615) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4044618: Tcl_EvalObjv (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3844) ==2077== by 0x4045641: TclEvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4643) ==2077== by 0x404542A: Tcl_EvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4555) ==2077== by 0x40E428C: Tcl_UplevelObjCmd (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:911) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4094C10: TclExecuteByteCode (/home/rolf/tcltk/tcl8.5.3/generic/tclExecute.c:2327) ==2077== by 0x40E5062: TclObjInterpProcCore (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:1721) ==2077== by 0x40E4FBC: TclObjInterpProc (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:1615) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4044618: Tcl_EvalObjv (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3844) ==2077== by 0x4045641: TclEvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4643) ==2077== by 0x404542A: Tcl_EvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4555) ==2077== by 0x40E428C: Tcl_UplevelObjCmd (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:911) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4094C10: TclExecuteByteCode (/home/rolf/tcltk/tcl8.5.3/generic/tclExecute.c:2327) ==2077== by 0x40E5062: TclObjInterpProcCore (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:1721) ==2077== by 0x40E4FBC: TclObjInterpProc (/home/rolf/tcltk/tcl8.5.3/generic/tclProc.c:1615) ==2077== by 0x40CC576: InvokeImportedCmd (/home/rolf/tcltk/tcl8.5.3/generic/tclNamesp.c:1889) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4094C10: TclExecuteByteCode (/home/rolf/tcltk/tcl8.5.3/generic/tclExecute.c:2327) ==2077== by 0x40931A3: TclCompEvalObj (/home/rolf/tcltk/tcl8.5.3/generic/tclExecute.c:1473) ==2077== by 0x404589D: TclEvalObjEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4763) ==2077== by 0x40AD119: SlaveEval (/home/rolf/tcltk/tcl8.5.3/generic/tclInterp.c:2479) ==2077== by 0x40ACC31: SlaveObjCmd (/home/rolf/tcltk/tcl8.5.3/generic/tclInterp.c:2288) ==2077== by 0x4044126: TclEvalObjvInternal (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:3649) ==2077== by 0x4045021: TclEvalEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4296) ==2077== by 0x404479F: Tcl_EvalEx (/home/rolf/tcltk/tcl8.5.3/generic/tclBasic.c:4002) ==2077== by 0x40C1D43: Tcl_FSEvalFileEx (/home/rolf/tcltk/tcl8.5.3/generic/tclIOUtil.c:1820) ==2077== by 0x40C9CD7: Tcl_Main (/home/rolf/tcltk/tcl8.5.3/generic/tclMain.c:441) ==2077== by 0x804C975: main (/home/rolf/tcltk/tcl8.5.3/unix/tclAppInit.c:87) ==2077== ==2077== LEAK SUMMARY: ==2077== definitely lost: 24 bytes in 1 blocks. ==2077== indirectly lost: 194 bytes in 7 blocks. ==2077== possibly lost: 0 bytes in 0 blocks. ==2077== still reachable: 0 bytes in 0 blocks. ==2077== suppressed: 0 bytes in 0 blocks. pointsman added on 2008-06-29 23:36:20: Logged In: YES user_id=13222 Originator: NO The fix seems to leak. With 8.5.3rc0 w/ 2004654 patch the following script shows the leak: while 1 { interp create moo moo eval { package require tcltest namespace import tcltest::* proc createfile {file {string a}} { set f [open $file w] puts -nonewline $f $string close $f return $string } proc cleanup {args} { set wd [list .] foreach p [concat $wd $args] { set x "" catch { set x [glob -directory $p tf* td*] } foreach file $x { if { [catch {file delete -force -- $file}] && [testConstraint testchmod] } then { catch {openup $file} catch {file delete -force -- $file} } } } } for {set i 0} {$i < 1000} {incr i} { test fCmd-10.11 {file copy: copy to empty file name} -setup { cleanup } -returnCodes error -body { createfile tf1 file copy tf1 "" } -result {error copying "tf1" to "": no such file or directory} } } puts moo interp delete moo } The script leaks slowly enough, to be watched with top without danger. The tests fCmd-10.11 and fCmd-10.12 out of the test suite trigger the leak. Attached is the relevant part of a valgrind output (-DPURIFY build). dgp added on 2008-06-25 03:06:47: Logged In: YES user_id=80530 Originator: NO patch committed for 8.6a1 and 8.5.3. No backport to 8.4.* since the bug hasn't been demo'd there. dgp added on 2008-06-25 03:00:00: File Added - 282525: 1999716.patch Logged In: YES user_id=80530 Originator: NO here's a patch to stop the crash without redesigning the world File Added: 1999716.patch dgp added on 2008-06-25 00:34:09: Logged In: YES user_id=80530 Originator: NO Lines 1773-1774 are more reasonable than I thought. When they run, we have already called Tcl_FSGetNormalizedPath() on fsPathPtr->cwdPtr, so for any normal value, that call should have established cwdPtr!=NULL. That's only false because the empty string value as a pathname is so weird (see 2001389). dgp added on 2008-06-24 04:30:15: Logged In: YES user_id=80530 Originator: NO From the comments about 'struct FsPath' on lines 57-64 of tclPathObj.c: * (i) flags == 0, => Ordinary path. * * translatedPathPtr contains the translated path (which may be a circular * reference to the object itself). If it is NULL then the path is pure * normalized (and the normPathPtr will be a circular reference). cwdPtr is * null for an absolute path, and non-null for a relative path (unless the cwd * has never been set, in which case the cwdPtr may also be null for a * relative path). Take care to note that cwdPtr==NULL is possible for a relative path when the global cwd has never been set. The code at lines 1773-1174 (in Tcl_FSGetNormalizedPath()) fails to account for this possibility. dgp added on 2008-06-24 01:20:23: Logged In: YES user_id=80530 Originator: NO Add the command cd [pwd] before the [glob] and the crash doesn't happen. Suggests that at least one contibutor to the error is that Tcl's internal record of what is the current working directory is not initialized at a time when other parts of Tcl's filesystem code may be assuming that it is initialized. dgp added on 2008-06-23 21:49:20: Logged In: YES user_id=80530 Originator: NO % glob -nocomplain -directory {} anything Program received signal SIGSEGV, Segmentation fault. 0x0807c3db in Tcl_DbIncrRefCount (objPtr=0x0, file=0x8172768 "/home/dgp/cvs/tcl/unix/../generic/tclPathObj.c", line=1772) at /home/dgp/cvs/tcl/unix/../generic/tclObj.c:3088 3088 if (objPtr->refCount == 0x61616161) { (gdb) bt #0 0x0807c3db in Tcl_DbIncrRefCount (objPtr=0x0, file=0x8172768 "/home/dgp/cvs/tcl/unix/../generic/tclPathObj.c", line=1772) at /home/dgp/cvs/tcl/unix/../generic/tclObj.c:3088 #1 0x080827a8 in Tcl_FSGetNormalizedPath (interp=0x0, pathPtr=0x9d1e850) at /home/dgp/cvs/tcl/unix/../generic/tclPathObj.c:1772 #2 0x080ae733 in TclNativeCreateNativeRep (pathPtr=0x9d1e850) at /home/dgp/cvs/tcl/unix/../unix/tclUnixFile.c:1104 #3 0x08082d79 in Tcl_FSGetInternalRep (pathPtr=0x9d1e850, fsPtr=0x8188f40) at /home/dgp/cvs/tcl/unix/../generic/tclPathObj.c:2069 #4 0x0806bb9b in Tcl_FSGetNativePath (pathPtr=0x9d1e850) at /home/dgp/cvs/tcl/unix/../generic/tclIOUtil.c:4290 #5 0x080ad679 in TclpMatchInDirectory (interp=0x9cd18c8, resultPtr=0x9d13200, pathPtr=0x9d1e850, pattern=0x0, types=0x0) at /home/dgp/cvs/tcl/unix/../unix/tclUnixFile.c:235 #6 0x08068974 in Tcl_FSMatchInDirectory (interp=0x9cd18c8, resultPtr=0x9d13200, pathPtr=0x9d1e850, pattern=0x0, types=0x0) at /home/dgp/cvs/tcl/unix/../generic/tclIOUtil.c:1056 #7 0x081473d7 in DoGlob (interp=0x9cd18c8, matchesObj=0x9d13200, separators=0x8181bfe "/", pathPtr=0x9d06d18, flags=4, pattern=0x9d18080 "anything", types=0x0) at /home/dgp/cvs/tcl/unix/../generic/tclFileName.c:2457 dgp added on 2008-06-23 21:43:14: Logged In: YES user_id=80530 Originator: NO crashes on unix too. |
Attachments:
- 1999716.patch [download] added by dgp on 2008-06-25 03:00:00. [details]