Tcl Source Code

Check-in [7723c52623]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:merge bug-45b9faf103f2, fewer destructive TclObjLookupVarEx, closes [45b9faf103f2]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-branch
Files: files | file ages | folders
SHA3-256: 7723c526233deee00a4496427fa84df0a7df7929d5342f3853e5d5192c3ee5c1
User & Date: sebres 2019-04-08 15:35:29
Context
2019-04-08
21:25
Fix clang compiler warning in tclZlib.c. Clear execute bit in two encodings check-in: f49ac8ca52 user: jan.nijtmans tags: core-8-branch
19:06
Merge 8.7. Intended operation completed for mingw-w64 (but not yet for other compilers/platforms) check-in: 1c2054cc64 user: jan.nijtmans tags: digit-bit-60
15:35
merge bug-45b9faf103f2, fewer destructive TclObjLookupVarEx, closes [45b9faf103f2] check-in: 7723c52623 user: sebres tags: core-8-branch
15:03
closes [45b9faf103f2] (tclVar cached lookup): fixes segfaulting if variable released before set; par... Closed-Leaf check-in: e62a48e964 user: sebres tags: bug-45b9faf103f2
13:38
Improve test for last commit fixing [45b9faf103f2]. check-in: 55da18eb59 user: pooryorick tags: core-8-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclCmdMZ.c.

4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
	    Tcl_ResetResult(interp);
	    result = TCL_ERROR;
	    Tcl_ListObjLength(NULL, info[3], &dummy);
	    if (dummy > 0) {
		Tcl_Obj *varName;

		Tcl_ListObjIndex(NULL, info[3], 0, &varName);
		Tcl_IncrRefCount(varName);
		if (Tcl_ObjSetVar2(interp, varName, NULL, resultObj,
			TCL_LEAVE_ERR_MSG) == NULL) {
		    Tcl_DecrRefCount(varName);
		    Tcl_DecrRefCount(resultObj);
		    goto handlerFailed;
		}
		Tcl_DecrRefCount(varName);
		Tcl_DecrRefCount(resultObj);
		if (dummy > 1) {
		    Tcl_ListObjIndex(NULL, info[3], 1, &varName);
		    Tcl_IncrRefCount(varName);
		    if (Tcl_ObjSetVar2(interp, varName, NULL, options,
			    TCL_LEAVE_ERR_MSG) == NULL) {
			Tcl_DecrRefCount(varName);
			goto handlerFailed;
		    }
		    Tcl_DecrRefCount(varName);
		}
	    } else {
		/*
		 * Dispose of the result to prevent a memleak. [Bug 2910044]
		 */

		Tcl_DecrRefCount(resultObj);






<


<



<



<


<


<







4808
4809
4810
4811
4812
4813
4814

4815
4816

4817
4818
4819

4820
4821
4822

4823
4824

4825
4826

4827
4828
4829
4830
4831
4832
4833
	    Tcl_ResetResult(interp);
	    result = TCL_ERROR;
	    Tcl_ListObjLength(NULL, info[3], &dummy);
	    if (dummy > 0) {
		Tcl_Obj *varName;

		Tcl_ListObjIndex(NULL, info[3], 0, &varName);

		if (Tcl_ObjSetVar2(interp, varName, NULL, resultObj,
			TCL_LEAVE_ERR_MSG) == NULL) {

		    Tcl_DecrRefCount(resultObj);
		    goto handlerFailed;
		}

		Tcl_DecrRefCount(resultObj);
		if (dummy > 1) {
		    Tcl_ListObjIndex(NULL, info[3], 1, &varName);

		    if (Tcl_ObjSetVar2(interp, varName, NULL, options,
			    TCL_LEAVE_ERR_MSG) == NULL) {

			goto handlerFailed;
		    }

		}
	    } else {
		/*
		 * Dispose of the result to prevent a memleak. [Bug 2910044]
		 */

		Tcl_DecrRefCount(resultObj);

Changes to generic/tclVar.c.

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737








738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
	/*
	 * An indexed local variable.
	 */

	Tcl_Obj *cachedNamePtr = localName(varFramePtr, index);

	if (part1Ptr == cachedNamePtr) {
	    cachedNamePtr = NULL;
	} else {
	    /*
	     * [80304238ac] Trickiness here.  We will store and incr the
	     * refcount on cachedNamePtr.  Trouble is that it's possible
	     * (see test var-22.1) for cachedNamePtr to have an intrep
	     * that contains a stored and refcounted part1Ptr.  This
	     * would be a reference cycle which leads to a memory leak.
	     *
	     * The solution here is to wipe away all intrep(s) in
	     * cachedNamePtr and leave it as string only.  This is
	     * radical and destructive, so a better idea would be welcome.
	     */








	    TclFreeIntRep(cachedNamePtr);

	    /*
	     * Now go ahead and convert it the the "localVarName" type,
	     * since we suspect at least some use of the value as a
	     * varname and we want to resolve it quickly.
	     */
	    LocalSetIntRep(cachedNamePtr, index, NULL);
	}
	LocalSetIntRep(part1Ptr, index, cachedNamePtr);
    } else {
	/*
	 * At least mark part1Ptr as already parsed.
	 */

	ParsedSetIntRep(part1Ptr, NULL, NULL);
    }






|












>
>
>
>
>
>
>
>









<







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
	/*
	 * An indexed local variable.
	 */

	Tcl_Obj *cachedNamePtr = localName(varFramePtr, index);

	if (part1Ptr == cachedNamePtr) {
	    LocalSetIntRep(part1Ptr, index, NULL);
	} else {
	    /*
	     * [80304238ac] Trickiness here.  We will store and incr the
	     * refcount on cachedNamePtr.  Trouble is that it's possible
	     * (see test var-22.1) for cachedNamePtr to have an intrep
	     * that contains a stored and refcounted part1Ptr.  This
	     * would be a reference cycle which leads to a memory leak.
	     *
	     * The solution here is to wipe away all intrep(s) in
	     * cachedNamePtr and leave it as string only.  This is
	     * radical and destructive, so a better idea would be welcome.
	     */

	    /* 
	     * Firstly set cached local var reference (avoid free before set,
	     * see [45b9faf103f2])
	     */
	    LocalSetIntRep(part1Ptr, index, cachedNamePtr);

	    /* Then wipe it */
	    TclFreeIntRep(cachedNamePtr);

	    /*
	     * Now go ahead and convert it the the "localVarName" type,
	     * since we suspect at least some use of the value as a
	     * varname and we want to resolve it quickly.
	     */
	    LocalSetIntRep(cachedNamePtr, index, NULL);
	}

    } else {
	/*
	 * At least mark part1Ptr as already parsed.
	 */

	ParsedSetIntRep(part1Ptr, NULL, NULL);
    }