summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclStringObj.c38
-rw-r--r--tests/string.test30
2 files changed, 57 insertions, 11 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index aae52ba..aa99545 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -2916,10 +2916,10 @@ TclStringCatObjv(
last = objc - oc;
if (length == 0) {
first = last;
- }
- if ((length += numBytes) < 0) {
+ } else if (numBytes > INT_MAX - length) {
goto overflow;
}
+ length += numBytes;
}
}
} while (--oc);
@@ -2937,14 +2937,16 @@ TclStringCatObjv(
last = objc - oc;
if (length == 0) {
first = last;
- }
- if ((length += numChars) < 0) {
+ } else if (numChars > INT_MAX - length) {
goto overflow;
}
+ length += numChars;
}
}
} while (--oc);
} else {
+ Tcl_Obj *pendingPtr = NULL;
+
/* Result will be concat of string reps. Pre-size it. */
ov = objv; oc = objc;
do {
@@ -2952,15 +2954,29 @@ TclStringCatObjv(
objPtr = *ov++;
- Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */
- if (numBytes) {
+ if ((length == 0) && (objPtr->bytes == NULL) && !pendingPtr) {
+ /* No string rep; Take the chance we can avoid making it */
+
+ last = objc - oc;
+ first = last;
+ pendingPtr = objPtr;
+ } else {
+
+ Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */
+ if (numBytes == 0) {
+ continue;
+ }
last = objc - oc;
+ if (pendingPtr) {
+ Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */
+ pendingPtr = NULL;
+ }
if (length == 0) {
first = last;
- }
- if ((length += numBytes) < 0) {
+ } else if (numBytes > INT_MAX - length) {
goto overflow;
}
+ length += numBytes;
}
} while (--oc);
}
@@ -3073,9 +3089,9 @@ TclStringCatObjv(
return TCL_ERROR;
}
dst = Tcl_GetString(objResultPtr) + start;
- if (length > start) {
- TclFreeIntRep(objResultPtr);
- }
+
+ /* assert ( length > start ) */
+ TclFreeIntRep(objResultPtr);
} else {
objResultPtr = Tcl_NewObj(); /* PANIC? */
if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
diff --git a/tests/string.test b/tests/string.test
index fa7f8fb..9c43f29 100644
--- a/tests/string.test
+++ b/tests/string.test
@@ -1994,6 +1994,36 @@ test string-29.4 {string cat, many args} {
set r2 [string compare $xx [eval "string cat $vvs"]]
list $r1 $r2
} {0 0}
+test string-29.5 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat [list x] [list]]
+} -match glob -result {*no string representation}
+test string-29.6 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat [list] [list x]]
+} -match glob -result {*no string representation}
+test string-29.7 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat [list x] [list] [list]]
+} -match glob -result {*no string representation}
+test string-29.8 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat [list] [list x] [list]]
+} -match glob -result {*no string representation}
+test string-29.9 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat [list] [list] [list x]]
+} -match glob -result {*no string representation}
+test string-29.10 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat [list x] [list x]]
+} -match glob -result {*, string representation "xx"}
+test string-29.11 {string cat, efficiency} -body {
+ tcl::unsupported::representation \
+ [string cat [list x] [encoding convertto utf-8 {}]]
+} -match glob -result {*no string representation}
+test string-29.12 {string cat, efficiency} -body {
+ tcl::unsupported::representation \
+ [string cat [encoding convertto utf-8 {}] [list x]]
+} -match glob -result {*, string representation "x"}
+test string-29.13 {string cat, efficiency} -body {
+ tcl::unsupported::representation [string cat \
+ [encoding convertto utf-8 {}] [encoding convertto utf-8 {}] [list x]]
+} -match glob -result {*, string representation "x"}