Index: generic/tclVar.c ================================================================== --- generic/tclVar.c +++ generic/tclVar.c @@ -1738,10 +1738,11 @@ * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or * TCL_LEAVE_ERR_MSG. */ { Var *varPtr, *arrayPtr; + int newValRefCnt = newValuePtr->refCount; /* save original refCount */ /* * Filter to pass through only the flags this interface supports. */ @@ -1748,11 +1749,19 @@ flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG |TCL_APPEND_VALUE|TCL_LIST_ELEMENT); varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { - if (newValuePtr->refCount == 0) { + /* + * Free newValuePtr only if it had previously no references (otherwise + * the pointer newValRefCnt may be already released (during lookup, + * by rewriting of interpreter state with error, by trace call, etc.) + * + * TODO: check this can be sane rewritten using something like flag + * TCL_OWN_OBJREF as suggested in ticket [578155d5a19b348d]. + */ + if (newValRefCnt == 0) { /* not set and no other references */ Tcl_DecrRefCount(newValuePtr); } return NULL; } @@ -1805,10 +1814,11 @@ * found. */ { Interp *iPtr = (Interp *) interp; Tcl_Obj *oldValuePtr; Tcl_Obj *resultPtr = NULL; + int newValRefCnt = newValuePtr->refCount; /* save original refCount */ int result; /* * If the variable is in a hashtable and its hPtr field is NULL, then we * may have an upvar to an array element where the array was deleted or an @@ -1919,11 +1929,11 @@ TclDecrRefCount(oldValuePtr); oldValuePtr = varPtr->value.objPtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is ref */ } Tcl_AppendObjToObj(oldValuePtr, newValuePtr); - if (newValuePtr->refCount == 0) { + if (newValRefCnt == 0) { /* not set and no other references */ Tcl_DecrRefCount(newValuePtr); } } } } else if (newValuePtr != oldValuePtr) { @@ -1979,11 +1989,11 @@ TclCleanupVar(varPtr, arrayPtr); } return resultPtr; earlyError: - if (newValuePtr->refCount == 0) { + if (newValRefCnt == 0) { /* not set and no other references */ Tcl_DecrRefCount(newValuePtr); } goto cleanup; }