summaryrefslogtreecommitdiffstats
path: root/generic/tclUtil.c
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-05-20 16:39:50 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-05-20 16:39:50 (GMT)
commitf19e2665d309df5a484a53ea6d9b1098275e33db (patch)
tree6906aa04fcb87740b514d40f1b4c83435a53a645 /generic/tclUtil.c
parent72dfeb60e23c679d2c7258db4eb9ccce0a0661fa (diff)
parent96d441c29a2a47269655285a02c546765c163fd2 (diff)
downloadtcl-f19e2665d309df5a484a53ea6d9b1098275e33db.zip
tcl-f19e2665d309df5a484a53ea6d9b1098275e33db.tar.gz
tcl-f19e2665d309df5a484a53ea6d9b1098275e33db.tar.bz2
Fix [c9663296fd]. Also refactor memory reallocation.
Diffstat (limited to 'generic/tclUtil.c')
-rw-r--r--generic/tclUtil.c63
1 files changed, 33 insertions, 30 deletions
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index a195c10..67c7bc1 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -2606,34 +2606,35 @@ Tcl_DStringAppend(
if (length < 0) {
length = strlen(bytes);
}
- newSize = length + dsPtr->length;
- /*
- * Allocate a larger buffer for the string if the current one isn't large
- * enough. Allocate extra space in the new buffer so that there will be
- * room to grow before we have to allocate again.
- */
+ if (length > (TCL_SIZE_MAX - dsPtr->length - 1)) {
+ Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER
+ "d bytes) exceeded",
+ TCL_SIZE_MAX);
+ return NULL; /* NOTREACHED */
+ }
+ newSize = length + dsPtr->length + 1;
- if (newSize >= dsPtr->spaceAvl) {
- dsPtr->spaceAvl = newSize * 2;
- if (dsPtr->string == dsPtr->staticSpace) {
- char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
+ if (newSize > dsPtr->spaceAvl) {
+ if (dsPtr->string == dsPtr->staticSpace) {
+ char *newString;
+ newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
memcpy(newString, dsPtr->string, dsPtr->length);
dsPtr->string = newString;
} else {
- Tcl_Size index = TCL_INDEX_NONE;
+ Tcl_Size offset = -1;
/* See [16896d49fd] */
if (bytes >= dsPtr->string
&& bytes <= dsPtr->string + dsPtr->length) {
- index = bytes - dsPtr->string;
+ /* Source string is within this DString. Note offset */
+ offset = bytes - dsPtr->string;
}
-
- dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);
-
- if (index >= 0) {
- bytes = dsPtr->string + index;
+ dsPtr->string =
+ (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
+ if (offset >= 0) {
+ bytes = dsPtr->string + offset;
}
}
}
@@ -2745,12 +2746,11 @@ Tcl_DStringAppendElement(
* memcpy, not strcpy, to copy the string to a larger buffer, since there
* may be embedded NULLs in the string in some cases.
*/
-
- if (newSize >= dsPtr->spaceAvl) {
- dsPtr->spaceAvl = newSize * 2;
+ newSize += 1; /* For terminating nul */
+ if (newSize > dsPtr->spaceAvl) {
if (dsPtr->string == dsPtr->staticSpace) {
- char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);
-
+ char *newString;
+ newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
memcpy(newString, dsPtr->string, dsPtr->length);
dsPtr->string = newString;
} else {
@@ -2759,11 +2759,11 @@ Tcl_DStringAppendElement(
/* See [16896d49fd] */
if (element >= dsPtr->string
&& element <= dsPtr->string + dsPtr->length) {
+ /* Source string is within this DString. Note offset */
offset = element - dsPtr->string;
}
-
- dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);
-
+ dsPtr->string =
+ (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
if (offset >= 0) {
element = dsPtr->string + offset;
}
@@ -2822,13 +2822,16 @@ Tcl_DStringSetLength(
* would be wasteful to overallocate that buffer, so we just allocate
* enough for the requested size plus the trailing null byte. In the
* second case, we are growing the buffer incrementally, so we need
- * behavior similar to Tcl_DStringAppend. The requested length will
- * usually be a small delta above the current spaceAvl, so we'll end
- * up doubling the old size. This won't grow the buffer quite as
- * quickly, but it should be close enough.
+ * behavior similar to Tcl_DStringAppend.
+ * TODO - the above makes no sense to me. How does the code below
+ * translate into distinguishing the two cases above? IMO, if caller
+ * specifically sets the length, there is no cause for overallocation.
*/
- newsize = dsPtr->spaceAvl * 2;
+ if (length >= TCL_SIZE_MAX) {
+ Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded");
+ }
+ newsize = TclUpsizeAlloc(dsPtr->spaceAvl, length + 1, TCL_SIZE_MAX);
if (length < newsize) {
dsPtr->spaceAvl = newsize;
} else {