diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2004-08-30 18:15:24 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2004-08-30 18:15:24 (GMT) |
commit | 54f15bb144abf1e98db0a7bf90f741a93b41eff4 (patch) | |
tree | 39ee31674a5a0324d9368289abf06d114660122b /generic | |
parent | 9e7d1e52219a5f372c7a0dea6ef24110e03cee81 (diff) | |
download | tcl-54f15bb144abf1e98db0a7bf90f741a93b41eff4.zip tcl-54f15bb144abf1e98db0a7bf90f741a93b41eff4.tar.gz tcl-54f15bb144abf1e98db0a7bf90f741a93b41eff4.tar.bz2 |
Fix crash in [string map] when objects are shared. [Bug 1018562]
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclCmdMZ.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 09c3853..1bf2183 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -14,7 +14,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.82.2.11 2004/03/01 17:33:21 dgp Exp $ + * RCS: @(#) $Id: tclCmdMZ.c,v 1.82.2.12 2004/08/30 18:15:24 dkf Exp $ */ #include "tclInt.h" @@ -1857,8 +1857,8 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) break; } case STR_MAP: { - int mapElemc, nocase = 0; - Tcl_Obj **mapElemv; + int mapElemc, nocase = 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)); @@ -1898,13 +1898,26 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) Tcl_SetStringObj(resultPtr, "char map list unbalanced", -1); 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 */ + if (copySource) { + Tcl_DecrRefCount(sourceObj); + } break; } end = ustring1 + length1; @@ -2024,6 +2037,9 @@ Tcl_StringObjCmd(dummy, interp, objc, objv) */ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p); } + if (copySource) { + Tcl_DecrRefCount(sourceObj); + } break; } case STR_MATCH: { |