summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclStringObj.c35
1 files changed, 18 insertions, 17 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index a4c242a..c1c15f2 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -2897,7 +2897,7 @@ TclStringCatObjv(
if (binary) {
/* Result will be pure byte array. Pre-size it */
ov = objv; oc = objc;
- while (oc-- && (length >= 0)) {
+ while (oc--) {
objPtr = *ov++;
if (objPtr->bytes == NULL) {
@@ -2909,14 +2909,16 @@ TclStringCatObjv(
if (length == 0) {
first = last;
}
+ if ((length += numBytes) < 0) {
+ break; /* overflow */
+ }
}
- length += numBytes;
}
}
} else if (allowUniChar && requestUniChar) {
/* Result will be pure Tcl_UniChar array. Pre-size it. */
ov = objv; oc = objc;
- while (oc-- && (length >= 0)) {
+ while (oc--) {
objPtr = *ov++;
if ((objPtr->bytes == NULL) || (objPtr->length)) {
@@ -2929,13 +2931,15 @@ TclStringCatObjv(
first = last;
}
}
- length += numChars;
+ if ((length += numChars) < 0) {
+ break; /* overflow */
+ }
}
}
} else {
/* Result will be concat of string reps. Pre-size it. */
ov = objv; oc = objc;
- while (oc-- && (length >= 0)) {
+ while (oc--) {
int numBytes;
objPtr = *ov++;
@@ -2946,11 +2950,19 @@ TclStringCatObjv(
if (length == 0) {
first = last;
}
+ if ((length += numBytes) < 0) {
+ break; /* overflow */
+ }
}
- length += numBytes;
}
}
+ if (last == first || length == 0) {
+ /* Only one non-empty value or zero length; return first */
+ *objPtrPtr = objv[first];
+ return TCL_OK;
+ }
+
if (length < 0) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
@@ -2960,17 +2972,6 @@ TclStringCatObjv(
return TCL_ERROR;
}
- if (length == 0) {
- /* Total length of zero means every value has length zero */
- *objPtrPtr = objv[0];
- return TCL_OK;
- }
- if (last == first) {
- /* Only one non-empty value; return it */
- *objPtrPtr = objv[first];
- return TCL_OK;
- }
-
objv += first; objc = (last - first + 1);
if (binary) {