summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-05-03 13:18:05 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-05-03 13:18:05 (GMT)
commit688c125ec305e23f82299d3b321a9c262e8af35f (patch)
treed9bad154bfc3010cffe6924a9f61fc9499a00ace
parent06cc962945bd148c0fb2a63ab23e6e3577945929 (diff)
downloadtcl-688c125ec305e23f82299d3b321a9c262e8af35f.zip
tcl-688c125ec305e23f82299d3b321a9c262e8af35f.tar.gz
tcl-688c125ec305e23f82299d3b321a9c262e8af35f.tar.bz2
Fix bug-c9663296fd (in progress)
-rw-r--r--generic/tclStringObj.c56
-rw-r--r--generic/tclStringRep.h7
2 files changed, 38 insertions, 25 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index d2bc1b2..33e61a6 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -131,8 +131,8 @@ const Tcl_ObjType tclStringType = {
static void
GrowStringBuffer(
Tcl_Obj *objPtr,
- size_t needed,
- int flag)
+ size_t needed, /* Not including terminating nul */
+ int flag) /* If 0, try to overallocate */
{
/*
* Preconditions:
@@ -145,11 +145,18 @@ GrowStringBuffer(
char *ptr = NULL;
size_t attempt;
+ assert(needed <= TCL_SIZE_MAX - 1);
+
if (objPtr->bytes == &tclEmptyString) {
objPtr->bytes = NULL;
}
if (flag == 0 || stringPtr->allocated > 0) {
- attempt = 2 * needed;
+ if (needed <= (TCL_SIZE_MAX - needed - 1)) {
+ /* Doubling space will not overflow */
+ attempt = 2 * needed;
+ } else {
+ attempt = TCL_SIZE_MAX - 1;
+ }
ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1U);
if (ptr == NULL) {
/*
@@ -157,11 +164,11 @@ GrowStringBuffer(
* overflow into invalid argument values for attempt.
*/
- size_t limit = INT_MAX - needed;
- size_t extra = needed - objPtr->length + TCL_MIN_GROWTH;
- size_t growth = (extra > limit) ? limit : extra;
-
- attempt = needed + growth;
+ if (needed < (TCL_SIZE_MAX - TCL_MIN_GROWTH - 1)) {
+ attempt = needed + TCL_MIN_GROWTH;
+ } else {
+ attempt = TCL_SIZE_MAX - 1;
+ }
ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1U);
}
}
@@ -190,32 +197,37 @@ GrowUnicodeBuffer(
String *ptr = NULL, *stringPtr = GET_STRING(objPtr);
size_t attempt;
+ size_t bytesNeeded; /* Actual storage including header */
+ /* Note STRING_MAXCHARS already takes into account space for nul */
+ if (needed > STRING_MAXCHARS) {
+ Tcl_Panic("max size for a Tcl unicode rep (%" TCL_Z_MODIFIER "d bytes) exceeded",
+ STRING_MAXCHARS);
+ }
if (stringPtr->maxChars > 0) {
- /*
- * Subsequent appends - apply the growth algorithm.
- */
-
- attempt = 2 * needed;
+ /* Subsequent appends - apply the growth algorithm. */
+ if (needed <= (STRING_MAXCHARS - needed)) {
+ /* Doubling space will not overflow */
+ attempt = 2 * needed;
+ } else {
+ attempt = STRING_MAXCHARS;
+ }
ptr = stringAttemptRealloc(stringPtr, attempt);
if (ptr == NULL) {
/*
* Take care computing the amount of modest growth to avoid
* overflow into invalid argument values for attempt.
*/
-
- size_t extra = needed - stringPtr->numChars
- + TCL_MIN_UNICHAR_GROWTH;
-
- attempt = needed + extra;
+ if (needed < (STRING_MAXCHARS - TCL_MIN_GROWTH)) {
+ attempt = needed + TCL_MIN_GROWTH;
+ } else {
+ attempt = STRING_MAXCHARS;
+ }
ptr = stringAttemptRealloc(stringPtr, attempt);
}
}
if (ptr == NULL) {
- /*
- * First allocation - just big enough; or last chance fallback.
- */
-
+ /* First allocation - just big enough; or last chance fallback. */
attempt = needed;
ptr = stringRealloc(stringPtr, attempt);
}
diff --git a/generic/tclStringRep.h b/generic/tclStringRep.h
index 7f72b04..d4b6b2d 100644
--- a/generic/tclStringRep.h
+++ b/generic/tclStringRep.h
@@ -34,9 +34,10 @@ typedef struct {
* calculated. Any other means that there is a valid
* Unicode rep, or that the number of UTF bytes ==
* the number of chars. */
- Tcl_Size allocated; /* The amount of space actually allocated for
- * the UTF-8 string (minus 1 byte for the
- * termination char). */
+ Tcl_Size allocated; /* The amount of space allocated for
+ * the UTF-8 string. Does not include nul
+ * terminator so actual allocation is
+ * (allocated+1). */
Tcl_Size maxChars; /* Max number of chars that can fit in the
* space allocated for the Unicode array. */
int hasUnicode; /* Boolean determining whether the string has