summaryrefslogtreecommitdiffstats
path: root/generic/tclListObj.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2018-11-09 16:03:22 (GMT)
committerdgp <dgp@users.sourceforge.net>2018-11-09 16:03:22 (GMT)
commit5deb25bc9b71c984e1e0577b53b7664c1fab0315 (patch)
treea06be82e0f814165c21ee6cae49f3d72ed9855ef /generic/tclListObj.c
parent008a36f3e4b5daef7eadc65c63a98e40d62bd1e2 (diff)
parent0f4e877214d36d6ecbf31ae9fb60ea5ebb3dac0a (diff)
downloadtcl-5deb25bc9b71c984e1e0577b53b7664c1fab0315.zip
tcl-5deb25bc9b71c984e1e0577b53b7664c1fab0315.tar.gz
tcl-5deb25bc9b71c984e1e0577b53b7664c1fab0315.tar.bz2
merge 8.5
Diffstat (limited to 'generic/tclListObj.c')
-rw-r--r--generic/tclListObj.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index 786e1ce..e42567e 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -1990,7 +1990,21 @@ UpdateStringOfList(
* Pass 2: copy into string rep buffer.
*/
+ /*
+ * We used to set the string length here, relying on a presumed
+ * guarantee that the number of bytes TclScanElement() calls reported
+ * to be needed was a precise count and not an over-estimate, so long
+ * as the same flag values were passed to TclConvertElement().
+ *
+ * Then we saw [35a8f1c04a], where a bug in TclScanElement() caused
+ * that guarantee to fail. Rather than trust there are no more bugs,
+ * we set the length after the loop based on what was actually written,
+ * an not on what was predicted.
+ *
listPtr->length = bytesNeeded - 1;
+ *
+ */
+
listPtr->bytes = ckalloc(bytesNeeded);
dst = listPtr->bytes;
for (i = 0; i < numElems; i++) {
@@ -1999,7 +2013,10 @@ UpdateStringOfList(
dst += TclConvertElement(elem, length, dst, flagPtr[i]);
*dst++ = ' ';
}
- listPtr->bytes[listPtr->length] = '\0';
+ dst[-1] = '\0';
+
+ /* Here is the safe setting of the string length. */
+ listPtr->length = dst - 1 - listPtr->bytes;
if (flagPtr != localFlags) {
ckfree(flagPtr);