diff options
Diffstat (limited to 'generic/tclCmdIL.c')
| -rw-r--r-- | generic/tclCmdIL.c | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 2e68f67..70e2242 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -2307,20 +2307,22 @@ Tcl_LassignObjCmd( Tcl_Obj **listObjv; /* The contents of the list. */ Tcl_Size listObjc; /* The length of the list. */ Tcl_Size origListObjc; /* Original length */ - int code = TCL_OK; + int code; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "list ?varName ...?"); return TCL_ERROR; } - listCopyPtr = TclListObjCopy(interp, objv[1]); - if (listCopyPtr == NULL) { - return TCL_ERROR; - } + listCopyPtr = TclDuplicatePureObj(objv[1]); Tcl_IncrRefCount(listCopyPtr); /* Important! fs */ - TclListObjGetElementsM(NULL, listCopyPtr, &listObjc, &listObjv); + code = TclListObjGetElementsM( + interp, listCopyPtr, &listObjc, &listObjv); + if (code != TCL_OK) { + Tcl_DecrRefCount(listCopyPtr); + return code; + } origListObjc = listObjc; objc -= 2; @@ -2446,7 +2448,7 @@ Tcl_LinsertObjCmd( { Tcl_Obj *listPtr; Tcl_Size len, index; - int result; + int copied = 0, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?"); @@ -2479,7 +2481,8 @@ Tcl_LinsertObjCmd( listPtr = objv[1]; if (Tcl_IsShared(listPtr)) { - listPtr = TclListObjCopy(NULL, listPtr); + listPtr = TclDuplicatePureObj(listPtr); + copied = 1; } if ((objc == 4) && (index == len)) { @@ -2487,10 +2490,19 @@ Tcl_LinsertObjCmd( * Special case: insert one element at the end of the list. */ - Tcl_ListObjAppendElement(NULL, listPtr, objv[3]); + result = Tcl_ListObjAppendElement(NULL, listPtr, objv[3]); + if (result != TCL_OK) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } + return result; + } } else { if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3]))) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } return TCL_ERROR; } } @@ -2614,7 +2626,7 @@ Tcl_LpopObjCmd( /* Argument objects. */ { Tcl_Size listLen; - int result; + int copied = 0, result; Tcl_Obj *elemPtr, *stored; Tcl_Obj *listPtr, **elemPtrs; @@ -2666,18 +2678,26 @@ Tcl_LpopObjCmd( if (objc == 2) { if (Tcl_IsShared(listPtr)) { - listPtr = TclListObjCopy(NULL, listPtr); + listPtr = TclDuplicatePureObj(listPtr); + copied = 1; } result = Tcl_ListObjReplace(interp, listPtr, listLen - 1, 1, 0, NULL); if (result != TCL_OK) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } return result; } Tcl_IncrRefCount(listPtr); } else { - listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL); - - if (listPtr == NULL) { + Tcl_Obj *newListPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL); + if (newListPtr == NULL) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } return TCL_ERROR; + } else { + listPtr = newListPtr; } } @@ -2799,6 +2819,7 @@ Tcl_LremoveObjCmd( Tcl_Size i, idxc, prevIdx, first, num; Tcl_Size *idxv, listLen; Tcl_Obj *listObj; + int copied = 0, status = TCL_OK; /* * Parse the arguments. @@ -2821,10 +2842,10 @@ Tcl_LremoveObjCmd( } idxv = (Tcl_Size *)Tcl_Alloc((objc - 2) * sizeof(*idxv)); for (i = 2; i < objc; i++) { - if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1, - &idxv[i - 2]) != TCL_OK) { - Tcl_Free(idxv); - return TCL_ERROR; + status = (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1, + &idxv[i - 2]) != TCL_OK); + if (status != TCL_OK) { + goto done; } } @@ -2842,7 +2863,8 @@ Tcl_LremoveObjCmd( */ if (Tcl_IsShared(listObj)) { - listObj = TclListObjCopy(NULL, listObj); + listObj = TclDuplicatePureObj(listObj); + copied = 1; } num = 0; first = listLen; @@ -2877,18 +2899,28 @@ Tcl_LremoveObjCmd( * and we're only ever contracting that list. */ - (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + if (status != TCL_OK) { + goto done; + } listLen -= num; num = 1; first = idx; } } if (num != 0) { - (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + if (status != TCL_OK) { + if (copied) { + Tcl_DecrRefCount(listObj); + } + goto done; + } } - Tcl_Free(idxv); Tcl_SetObjResult(interp, listObj); - return TCL_OK; +done: + Tcl_Free(idxv); + return status; } /* @@ -3082,7 +3114,7 @@ Tcl_LreplaceObjCmd( listPtr = objv[1]; if (Tcl_IsShared(listPtr)) { - listPtr = TclListObjCopy(NULL, listPtr); + listPtr = TclDuplicatePureObj(listPtr); } /* @@ -3095,6 +3127,7 @@ Tcl_LreplaceObjCmd( if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, first, numToDelete, objc-4, objv+4)) { + Tcl_DecrRefCount(listPtr); return TCL_ERROR; } @@ -4709,7 +4742,7 @@ Tcl_LsortObjCmd( * 1675116] */ - listObj = TclListObjCopy(interp, listObj); + listObj = TclDuplicatePureObj(listObj); if (listObj == NULL) { sortInfo.resultCode = TCL_ERROR; goto done; @@ -4726,8 +4759,6 @@ Tcl_LsortObjCmd( if (Tcl_ListObjAppendElement(interp, newCommandPtr, newObjPtr) != TCL_OK) { TclDecrRefCount(newCommandPtr); - TclDecrRefCount(listObj); - Tcl_IncrRefCount(newObjPtr); TclDecrRefCount(newObjPtr); sortInfo.resultCode = TCL_ERROR; goto done; @@ -5067,7 +5098,7 @@ Tcl_LeditObjCmd( } if (Tcl_IsShared(listPtr)) { - listPtr = TclListObjCopy(NULL, listPtr); + listPtr = TclDuplicatePureObj(listPtr); createdNewObj = 1; } else { createdNewObj = 0; @@ -5084,18 +5115,10 @@ Tcl_LeditObjCmd( /* * Tcl_ObjSetVar2 may return a value different from listPtr in the - * presence of traces etc.. Note that finalValuePtr will always have a - * reference count of at least 1 corresponding to the reference from the - * var. If it is same as listPtr, then ref count will be at least 2 - * since we are incr'ing the latter below (safer when calling - * Tcl_ObjSetVar2 which can release it in some cases). Note that we - * leave the incrref of listPtr this late because we want to pass it as - * unshared to Tcl_ListObjReplace above if possible. + * presence of traces etc. */ - Tcl_IncrRefCount(listPtr); finalValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG); - Tcl_DecrRefCount(listPtr); /* safe irrespective of createdNewObj */ if (finalValuePtr == NULL) { return TCL_ERROR; } |
