summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2004-08-30 18:06:31 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2004-08-30 18:06:31 (GMT)
commitc7493debeb024f44455ae48fd9cbbe60d7f32207 (patch)
treeef77a0abbea975f1607d25e74f06e1f3eae603b1 /generic
parent0a024e8b7bb168a944277a4a466e71823d9bd9ad (diff)
downloadtcl-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')
-rw-r--r--generic/tclCmdMZ.c27
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: {