From 5a3d2ddfede6842bc089bd78d0c80fad82f911b0 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 2 Nov 2022 16:28:59 +0000 Subject: Bug #0f98bce669 - string cat support for > 2**31 characters. Tests pending --- generic/tcl.h | 1 - generic/tclInt.h | 5 +++++ generic/tclStringObj.c | 14 ++++++++++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index be39d2f..706c5f1 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -668,7 +668,6 @@ typedef size_t Tcl_Size; #else typedef int Tcl_Size; #endif -#define TCL_SIZE_SMAX ((((Tcl_Size) 1) << ((8*sizeof(Tcl_Size)) - 1)) - 1) typedef struct Tcl_Obj { diff --git a/generic/tclInt.h b/generic/tclInt.h index a7985f7..39ddef2 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -105,6 +105,11 @@ #endif /* + * Maximum *signed* value that can be stored in a Tcl_Size type. + */ +#define TCL_SIZE_SMAX ((((Tcl_Size) 1) << ((8*sizeof(Tcl_Size)) - 1)) - 1) + +/* * Macros used to cast between pointers and integers (e.g. when storing an int * in ClientData), on 64-bit architectures they avoid gcc warning about "cast * to/from pointer from/to integer of different size". diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 60dfa4d..008ece9 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3089,7 +3089,7 @@ TclStringCat( { Tcl_Obj *objResultPtr, * const *ov; int oc, binary = 1; - size_t length = 0; + size_t length = 0; int allowUniChar = 1, requestUniChar = 0, forceUniChar = 0; int first = objc - 1; /* Index of first value possibly not empty */ int last = 0; /* Index of last value possibly not empty */ @@ -3171,6 +3171,9 @@ TclStringCat( if (length == 0) { first = last; } + if (length > (TCL_SIZE_SMAX-numBytes)) { + goto overflow; + } length += numBytes; } } @@ -3194,6 +3197,9 @@ TclStringCat( if (length == 0) { first = last; } + if (length > ((TCL_SIZE_SMAX/sizeof(Tcl_UniChar))-numChars)) { + goto overflow; + } length += numChars; } } @@ -3258,7 +3264,7 @@ TclStringCat( if (numBytes) { first = last; } - } else if (numBytes + length > (size_t)INT_MAX) { + } else if (numBytes > (TCL_SIZE_SMAX - length)) { goto overflow; } length += numBytes; @@ -3275,7 +3281,7 @@ TclStringCat( numBytes = objPtr->length; if (numBytes) { last = objc - oc; - if (numBytes + length > (size_t)INT_MAX) { + if (numBytes > (TCL_SIZE_SMAX - length)) { goto overflow; } length += numBytes; @@ -3434,7 +3440,7 @@ TclStringCat( overflow: if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); + "max size for a Tcl value (%u" TCL_Z_MODIFIER " bytes) exceeded", TCL_SIZE_SMAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return NULL; -- cgit v0.12