diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclListObj.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/generic/tclListObj.c b/generic/tclListObj.c index e83a8f4..2c5c4d4 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclListObj.c,v 1.27 2005/09/06 14:40:11 dkf Exp $ + * RCS: @(#) $Id: tclListObj.c,v 1.28 2005/10/20 12:21:44 msofer Exp $ */ #include "tclInt.h" @@ -1112,12 +1112,21 @@ TclLsetFlat(interp, listPtr, indexCount, indexArray, valuePtr) } /* - * If the list is shared, make a private copy. + * If the list is shared, make a private copy. Duplicate the intrep to + * insure that it is modifyable [Bug 1333036]. A plain Tcl_DuplicateObj + * will just increase the intrep's refCount without upping the sublists' + * refCount, so that their true shared status cannot be determined from + * their refCount. */ if (Tcl_IsShared(listPtr)) { duplicated = 1; - listPtr = Tcl_DuplicateObj(listPtr); + if (listPtr->typePtr == &tclListType) { + result = Tcl_ListObjGetElements(interp, listPtr, &elemCount, &elemPtrs); + listPtr = Tcl_NewListObj(elemCount, elemPtrs); + } else { + listPtr = Tcl_DuplicateObj(listPtr); + } Tcl_IncrRefCount(listPtr); } else { duplicated = 0; @@ -1182,12 +1191,20 @@ TclLsetFlat(interp, listPtr, indexCount, indexArray, valuePtr) } /* - * Extract the appropriate sublist, and make sure that it is unshared. + * Extract the appropriate sublist, and make sure that it is unshared. + * If it is a list, duplicate the intrep to avoid [Bug 1333036], as + * per the previous comment. */ subListPtr = elemPtrs[index]; if (Tcl_IsShared(subListPtr)) { - subListPtr = Tcl_DuplicateObj(subListPtr); + if (subListPtr->typePtr == &tclListType) { + result = Tcl_ListObjGetElements(interp, subListPtr, &elemCount, + &elemPtrs); + subListPtr = Tcl_NewListObj(elemCount, elemPtrs); + } else { + subListPtr = Tcl_DuplicateObj(subListPtr); + } result = TclListObjSetElement(interp, listPtr, index, subListPtr); if (result != TCL_OK) { /* |