diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2004-08-30 18:06:31 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2004-08-30 18:06:31 (GMT) |
commit | c7493debeb024f44455ae48fd9cbbe60d7f32207 (patch) | |
tree | ef77a0abbea975f1607d25e74f06e1f3eae603b1 /generic/tclCmdMZ.c | |
parent | 0a024e8b7bb168a944277a4a466e71823d9bd9ad (diff) | |
download | tcl-c7493debeb024f44455ae48fd9cbbe60d7f32207.zip tcl-c7493debeb024f44455ae48fd9cbbe60d7f32207.tar.gz tcl-c7493debeb024f44455ae48fd9cbbe60d7f32207.tar.bz2 |
Fix a crash caused by sharing in [string map]. [Bug 1018562]
Diffstat (limited to 'generic/tclCmdMZ.c')
-rw-r--r-- | generic/tclCmdMZ.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index f41bfaf..235a9f9 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCmdMZ.c,v 1.104 2004/07/07 14:00:05 dgp Exp $ + * RCS: @(#) $Id: tclCmdMZ.c,v 1.105 2004/08/30 18:06:33 dkf Exp $ */ #include "tclInt.h" @@ -1983,8 +1983,8 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) break; } case STR_MAP: { - int mapElemc, nocase = 0, mapWithDict = 0; - Tcl_Obj **mapElemv; + int mapElemc, nocase = 0, mapWithDict = 0, copySource = 0; + Tcl_Obj **mapElemv, *sourceObj; Tcl_UniChar *ustring1, *ustring2, *p, *end; int (*strCmpFn)_ANSI_ARGS_((CONST Tcl_UniChar*, CONST Tcl_UniChar*, unsigned long)); @@ -2006,6 +2006,7 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) } } + /* * This test is tricky, but has to be that way or you get * other strange inconsistencies (see test string-10.20 @@ -2060,9 +2061,19 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) return TCL_ERROR; } } - objc--; - ustring1 = Tcl_GetUnicodeFromObj(objv[objc], &length1); + /* + * Take a copy of the source string object if it is the + * same as the map string to cut out nasty sharing + * crashes. [Bug 1018562] + */ + if (objv[objc-2] == objv[objc-1]) { + sourceObj = Tcl_DuplicateObj(objv[objc-1]); + copySource = 1; + } else { + sourceObj = objv[objc-1]; + } + ustring1 = Tcl_GetUnicodeFromObj(sourceObj, &length1); if (length1 == 0) { /* * Empty input string, just stop now @@ -2070,6 +2081,9 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) if (mapWithDict) { ckfree((char *) mapElemv); } + if (copySource) { + Tcl_DecrRefCount(sourceObj); + } break; } end = ustring1 + length1; @@ -2192,6 +2206,9 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) if (mapWithDict) { ckfree((char *) mapElemv); } + if (copySource) { + Tcl_DecrRefCount(sourceObj); + } break; } case STR_MATCH: { |