Tcl Source Code

Check-in [a9c542391a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix for [6d4e9d1af5bf5b7d]: Memory leak: SetFsPathFromAny, assisted by the global literal table, causes a Tcl_Obj to reference itself.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-branch
Files: files | file ages | folders
SHA3-256: a9c542391a86a9e8d676aa17f0c1c09bf6cc9ca5d0503931dfacb67900cec51c
User & Date: pooryorick 2023-03-26 15:07:56
Original Comment: Fix for 6d4e9d1af5bf5b7d: Memory leak: SetFsPathFromAny, assisted by the global literal table, causes a Tcl_Obj to reference itself.
References
2023-03-26
15:10 Pending ticket [6d4e9d1af5]: memory leak: SetFsPathFromAny, assisted by the global literal table, causes a Tcl_Obj to reference itself plus 4 other changes artifact: dab9b2e1cc user: pooryorick
Context
2023-03-26
16:42
Merge-mark: Valgrind reports no memory leaks. check-in: 78b5eed1f2 user: pooryorick tags: core-8-branch
15:35
Fix for [6d4e9d1af5bf5b7d]: Memory leak: SetFsPathFromAny, assisted by the global literal table, ca... check-in: 7d005e0860 user: pooryorick tags: trunk, main
15:07
Fix for [6d4e9d1af5bf5b7d]: Memory leak: SetFsPathFromAny, assisted by the global literal table, ca... check-in: a9c542391a user: pooryorick tags: core-8-branch
15:02
Fix for [6d4e9d1af5bf5b7d]: Memory leak: SetFsPathFromAny, assisted by the global literal table, ca... Closed-Leaf check-in: fb9a2adbd2 user: pooryorick tags: bug-6d4e9d1af5bf5b7d
2023-03-24
21:08
Fix [68417a8bb3]: No result/LF printed for 64-bit integer type check check-in: 5aff89ad15 user: jan.nijtmans tags: core-8-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclPathObj.c.

2346
2347
2348
2349
2350
2351
2352


2353
2354
2355
2356
2357
2358
2359
     * Now we have a translated filename in 'transPtr'. This will have forward
     * slashes on Windows, and will not contain any ~user sequences.
     */

    fsPathPtr = (FsPath *)ckalloc(sizeof(FsPath));

    if (transPtr == pathPtr) {


        transPtr = Tcl_DuplicateObj(pathPtr);
        fsPathPtr->filesystemEpoch = 0;
    } else {
        fsPathPtr->filesystemEpoch = TclFSEpoch();
    }
    Tcl_IncrRefCount(transPtr);
    fsPathPtr->translatedPathPtr = transPtr;







>
>







2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
     * Now we have a translated filename in 'transPtr'. This will have forward
     * slashes on Windows, and will not contain any ~user sequences.
     */

    fsPathPtr = (FsPath *)ckalloc(sizeof(FsPath));

    if (transPtr == pathPtr) {
	Tcl_GetStringFromObj(pathPtr, NULL);
	TclFreeInternalRep(pathPtr);
        transPtr = Tcl_DuplicateObj(pathPtr);
        fsPathPtr->filesystemEpoch = 0;
    } else {
        fsPathPtr->filesystemEpoch = TclFSEpoch();
    }
    Tcl_IncrRefCount(transPtr);
    fsPathPtr->translatedPathPtr = transPtr;

Changes to tests/fileName.test.

14
15
16
17
18
19
20

21
22
23
24
25
26
27
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}


::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]


testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]
testConstraint linkDirectory 1
testConstraint symbolicLinkFile 1
if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) < 5.0 \







>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}


::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
source [file join [file dirname [info script]] tcltests.tcl]

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]
testConstraint linkDirectory 1
testConstraint symbolicLinkFile 1
if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) < 5.0 \
1625
1626
1627
1628
1629
1630
1631




























































1632
1633
1634
1635
1636
1637
1638
   glob -nocomplain -directory ~ -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    removeDirectory sub ~
} -result ~/sub/fileName-20.10





























































# cleanup
catch {file delete -force C:/globTest}
cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
catch {removeDirectory tcl[pid]}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
   glob -nocomplain -directory ~ -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    removeDirectory sub ~
} -result ~/sub/fileName-20.10


apply [list {} {
    test fileName-6d4e9d1af5bf5b7d {
	memory leak in SetFsPathFromAny

	Runs under both a TCL_DEBUG_MEM build and a -DPURIFY build for
	valgrind, which is useful since Valgrind provides information about the
	error location, but [memory] doesn't.
    } -setup {
	makeFile {puts "In script"} script

	if {[namespace which ::memory] eq {}} {
	    set memcheckcmd [list ::apply [list script {
		uplevel 1 $script
		return 0
	    } [namespace current]]]
	} else {
	    set memcheckcmd ::tcltests::scriptmemcheck
	}
    } -body {
	{*}$memcheckcmd {
	    set interp [interp create]
	    interp eval $interp {
		apply [list {} {
		    upvar 1 f f 

		    # A unique name so that no internal representation of this
		    # literal value has been picked up from any other script
		    # that has alredy been sourced into this interpreter.
		    set variableUniqueInTheEntireTclCodebase a
		    set name variableUniqueInTheEntireTclCodebase

		    # give the Tcl_Obj for "var1" an internal representation of
		    # type 'localVarNameType'.
		    set $name

		    set f [open variableUniqueInTheEntireTclCodebase w]
			try {
				puts $f {some data}
			} finally {
				close $f
			}

		    set f [open variableUniqueInTheEntireTclCodebase]
			try {
				read $f
			} finally {
				catch {file delete variableUniqueInTheEntireTclCodebase}
				close $f
			}
		} [namespace current]]
	    }
	    interp delete $interp
	}
    } -result 0
} [namespace current]]
    



# cleanup
catch {file delete -force C:/globTest}
cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
catch {removeDirectory tcl[pid]}

Changes to tests/tcltests.tcl.

29
30
31
32
33
34
35












36
37
38
39
40
41
42
	    interp alias {} [namespace current]::tempdir {} [
		namespace current]::tempdir_alternate
	} else {
	    interp alias {} [namespace current]::tempdir {} ::tcl::file::tempdir
	}
    }














    proc tempdir_alternate {} {
	close [file tempfile tempfile]
	set tmpdir [file dirname $tempfile]
	set execname [info nameofexecutable]
	regsub -all {[^[:alpha:][:digit:]]} $execname _ execname
	for {set i 0} {$i < 10000} {incr i} {







>
>
>
>
>
>
>
>
>
>
>
>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	    interp alias {} [namespace current]::tempdir {} [
		namespace current]::tempdir_alternate
	} else {
	    interp alias {} [namespace current]::tempdir {} ::tcl::file::tempdir
	}
    }


    # Stolen from dict.test
    proc scriptmemcheck script {
	set end [lindex [split [memory info] \n] 3 3]
	for {set i 0} {$i < 5} {incr i} {
	    uplevel 1 $script
	    set tmp $end
	    set end [lindex [split [memory info] \n] 3 3]
	}
	expr {$end - $tmp}
    }


    proc tempdir_alternate {} {
	close [file tempfile tempfile]
	set tmpdir [file dirname $tempfile]
	set execname [info nameofexecutable]
	regsub -all {[^[:alpha:][:digit:]]} $execname _ execname
	for {set i 0} {$i < 10000} {incr i} {