Tcl Source Code

Check-in [046a5af026]
Login
Bounty program for improvements to Tcl and certain Tcl packages.

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

Overview
Comment:Fix for issue [4f6a1ebd64]: ensemble: segmentation fault when -subcommand and -map values are the same object.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-branch
Files: files | file ages | folders
SHA3-256: 046a5af026d82a5c10012e96e9ee8c9e2de7936f79d8b253fbeebbb2d6b7d436
User & Date: pooryorick 2017-11-25 16:36:22
References
2017-11-29
13:59
Cherry-picked test-cases from [046a5af026]: fix for issue [4f6a1ebd64]: ensemble: segmentation fault... check-in: 2f25d1a37b user: sebres tags: core-8-5-branch
2017-11-25
16:41 Closed ticket [4f6a1ebd64]: ensemble: segmentation fault when -subcommand and -map values are the same object plus 6 other changes artifact: 2362961bbc user: pooryorick
Context
2017-11-29
13:59
Cherry-picked test-cases from [046a5af026]: fix for issue [4f6a1ebd64]: ensemble: segmentation fault... check-in: 2f25d1a37b user: sebres tags: core-8-5-branch
2017-11-28
18:06
Pulling changes from the last core-8-branch that doesn't cause a segfault in kits check-in: 7cfb94f9af user: hypnotoad tags: core_zip_vfs
2017-11-25
16:53
merge pyk-command-named-colon check-in: e76a04e48f user: pooryorick tags: core-8-branch
16:36
Fix for issue [4f6a1ebd64]: ensemble: segmentation fault when -subcommand and -map values are the sa... check-in: 046a5af026 user: pooryorick tags: core-8-branch
2017-11-21
22:46
merge pspjuth-cminmax check-in: cf212282b0 user: pspjuth tags: core-8-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclEnsemble.c.

2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
....
2549
2550
2551
2552
2553
2554
2555




2556




2557
2558
2559
2560
2561
2562
2563
....
2574
2575
2576
2577
2578
2579
2580



2581
2582
2583
2584
2585
2586
2587
{
    Tcl_HashSearch search;	/* Used for scanning the set of commands in
				 * the namespace that backs up this
				 * ensemble. */
    int i, j, isNew;
    Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
    Tcl_HashEntry *hPtr;


    if (hash->numEntries != 0) {
	/*
	 * Remove pre-existing table.
	 */

	ckfree(ensemblePtr->subcommandArrayPtr);
................................................................................
	    }

	    /*
	     * Look in our dictionary (if present) for the command.
	     */

	    if (ensemblePtr->subcommandDict != NULL) {




		Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i],




			&target);
		if (target != NULL) {
		    Tcl_SetHashValue(hPtr, target);
		    Tcl_IncrRefCount(target);
		    continue;
		}
	    }
................................................................................
	    } else {
		Tcl_AppendStringsToObj(cmdObj, name, NULL);
	    }
	    cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
	    Tcl_SetHashValue(hPtr, cmdPrefixObj);
	    Tcl_IncrRefCount(cmdPrefixObj);
	}



    } else if (ensemblePtr->subcommandDict != NULL) {
	/*
	 * No subcmd list, but we do have a mapping dictionary so we should
	 * use the keys of that. Convert the dictionary's contents into the
	 * form required for the ensemble's internal hashtable.
	 */







>







 







>
>
>
>
|
>
>
>
>







 







>
>
>







2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
....
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
....
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
{
    Tcl_HashSearch search;	/* Used for scanning the set of commands in
				 * the namespace that backs up this
				 * ensemble. */
    int i, j, isNew;
    Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
    Tcl_HashEntry *hPtr;
    Tcl_Obj *subcmdDictCopy = NULL ;

    if (hash->numEntries != 0) {
	/*
	 * Remove pre-existing table.
	 */

	ckfree(ensemblePtr->subcommandArrayPtr);
................................................................................
	    }

	    /*
	     * Look in our dictionary (if present) for the command.
	     */

	    if (ensemblePtr->subcommandDict != NULL) {
		if (subcmdDictCopy == NULL) {
		    if (ensemblePtr->subcmdList == ensemblePtr->subcommandDict) {
			subcmdDictCopy = Tcl_DuplicateObj(ensemblePtr->subcommandDict);
		    } else {
			subcmdDictCopy = ensemblePtr->subcommandDict; 
		    }
		    Tcl_IncrRefCount(subcmdDictCopy);
		}
		Tcl_DictObjGet(NULL, subcmdDictCopy, subcmdv[i],
			&target);
		if (target != NULL) {
		    Tcl_SetHashValue(hPtr, target);
		    Tcl_IncrRefCount(target);
		    continue;
		}
	    }
................................................................................
	    } else {
		Tcl_AppendStringsToObj(cmdObj, name, NULL);
	    }
	    cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
	    Tcl_SetHashValue(hPtr, cmdPrefixObj);
	    Tcl_IncrRefCount(cmdPrefixObj);
	}
	if (subcmdDictCopy != NULL) {
	    Tcl_DecrRefCount(subcmdDictCopy);
	}
    } else if (ensemblePtr->subcommandDict != NULL) {
	/*
	 * No subcmd list, but we do have a mapping dictionary so we should
	 * use the keys of that. Convert the dictionary's contents into the
	 * form required for the ensemble's internal hashtable.
	 */

Changes to tests/namespace.test.

1781
1782
1783
1784
1785
1786
1787
1788



1789
1790
1791
1792
1793
1794
1795
....
1796
1797
1798
1799
1800
1801
1802













1803
1804
1805
1806
1807
1808
1809
	proc x3 {} {format 3}
	namespace ensemble create
    }
    list [ns x0 z] [ns x1] [ns x2] [ns x3]
} -cleanup {
    namespace delete ns
} -result {{1 ::ns::x0::z} 1 2 3}
test namespace-42.8 {ensembles: [Bug 1670091]} -setup {



    proc demo args {}
    variable target [list [namespace which demo] x]
    proc trial args {variable target; string length $target}
    trace add execution demo enter [namespace code trial]
    namespace ensemble create -command foo -map [list bar $target]
} -body {
    foo bar
................................................................................
} -cleanup {
    unset target
    rename demo {}
    rename trial {}
    rename foo {}
} -result {}














test namespace-43.1 {ensembles: dict-driven} {
    namespace eval ns {
	namespace export x*
	proc x1 {} {format 1}
	proc x2 {} {format 2}
	namespace ensemble create -map {a x1 b x2}
    }






|
>
>
>







 







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







1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
....
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
	proc x3 {} {format 3}
	namespace ensemble create
    }
    list [ns x0 z] [ns x1] [ns x2] [ns x3]
} -cleanup {
    namespace delete ns
} -result {{1 ::ns::x0::z} 1 2 3}
test namespace-42.8 {
    ensembles: [Bug 1670091], panic due to pointer to a deallocated List
    struct.
} -setup {
    proc demo args {}
    variable target [list [namespace which demo] x]
    proc trial args {variable target; string length $target}
    trace add execution demo enter [namespace code trial]
    namespace ensemble create -command foo -map [list bar $target]
} -body {
    foo bar
................................................................................
} -cleanup {
    unset target
    rename demo {}
    rename trial {}
    rename foo {}
} -result {}

test namespace-42.9 {
    ensembles: [Bug 4f6a1ebd64], segmentation fault due to pointer to a
    deallocated List struct.
} -setup {
    namespace eval n {namespace ensemble create}
    dict set list one ::two
    namespace ensemble configure n -subcommands $list -map $list
} -body {
    n one
} -cleanup {
    namespace delete n
} -returnCodes error -match glob -result {invalid command name*}

test namespace-43.1 {ensembles: dict-driven} {
    namespace eval ns {
	namespace export x*
	proc x1 {} {format 1}
	proc x2 {} {format 2}
	namespace ensemble create -map {a x1 b x2}
    }