diff options
Diffstat (limited to 'generic/tclStringObj.c')
-rw-r--r-- | generic/tclStringObj.c | 408 |
1 files changed, 223 insertions, 185 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index bb2cddf..3063ea3 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -45,28 +45,28 @@ static void AppendPrintfToObjVA(Tcl_Obj *objPtr, const char *format, va_list argList); static void AppendUnicodeToUnicodeRep(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t appendNumChars); + const Tcl_UniChar *unicode, Tcl_Size appendNumChars); static void AppendUnicodeToUtfRep(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); + const Tcl_UniChar *unicode, Tcl_Size numChars); static void AppendUtfToUnicodeRep(Tcl_Obj *objPtr, - const char *bytes, size_t numBytes); + const char *bytes, Tcl_Size numBytes); static void AppendUtfToUtfRep(Tcl_Obj *objPtr, - const char *bytes, size_t numBytes); + const char *bytes, Tcl_Size numBytes); static void DupStringInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); -static size_t ExtendStringRepWithUnicode(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); +static Tcl_Size ExtendStringRepWithUnicode(Tcl_Obj *objPtr, + const Tcl_UniChar *unicode, Tcl_Size numChars); static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr, - const char *bytes, size_t numBytes, - size_t numAppendChars); + const char *bytes, Tcl_Size numBytes, + Tcl_Size numAppendChars); static void FillUnicodeRep(Tcl_Obj *objPtr); static void FreeStringInternalRep(Tcl_Obj *objPtr); static void GrowStringBuffer(Tcl_Obj *objPtr, size_t needed, int flag); static void GrowUnicodeBuffer(Tcl_Obj *objPtr, size_t needed); static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void SetUnicodeObj(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); -static size_t UnicodeLength(const Tcl_UniChar *unicode); + const Tcl_UniChar *unicode, Tcl_Size numChars); +static Tcl_Size UnicodeLength(const Tcl_UniChar *unicode); static void UpdateStringOfString(Tcl_Obj *objPtr); #if TCL_UTF_MAX > 3 @@ -257,7 +257,7 @@ Tcl_Obj * Tcl_NewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length) /* The number of bytes to copy from "bytes" + Tcl_Size length) /* The number of bytes to copy from "bytes" * when initializing the new object. If * TCL_INDEX_NONE, use bytes up to the first NUL * byte. */ @@ -269,13 +269,13 @@ Tcl_Obj * Tcl_NewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length) /* The number of bytes to copy from "bytes" + Tcl_Size length) /* The number of bytes to copy from "bytes" * when initializing the new object. If -1, * use bytes up to the first NUL byte. */ { Tcl_Obj *objPtr; - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = (bytes? strlen(bytes) : 0); } TclNewStringObj(objPtr, bytes, length); @@ -317,7 +317,7 @@ Tcl_Obj * Tcl_DbNewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length, /* The number of bytes to copy from "bytes" + Tcl_Size length, /* The number of bytes to copy from "bytes" * when initializing the new object. If -1, * use bytes up to the first NUL byte. */ const char *file, /* The name of the source file calling this @@ -339,7 +339,7 @@ Tcl_Obj * Tcl_DbNewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length, /* The number of bytes to copy from "bytes" + Tcl_Size length, /* The number of bytes to copy from "bytes" * when initializing the new object. If -1, * use bytes up to the first NUL byte. */ TCL_UNUSED(const char *) /*file*/, @@ -372,7 +372,7 @@ Tcl_Obj * Tcl_NewUnicodeObj( const Tcl_UniChar *unicode, /* The unicode string used to initialize the * new object. */ - size_t numChars) /* Number of characters in the unicode + Tcl_Size numChars) /* Number of characters in the unicode * string. */ { Tcl_Obj *objPtr; @@ -399,13 +399,13 @@ Tcl_NewUnicodeObj( *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_GetCharLength( Tcl_Obj *objPtr) /* The String object to get the num chars * of. */ { String *stringPtr; - size_t numChars = 0; + Tcl_Size numChars = 0; /* * Quick, no-shimmer return for short string reps. @@ -444,19 +444,19 @@ Tcl_GetCharLength( * If numChars is unknown, compute it. */ - if (numChars == TCL_INDEX_NONE) { + if (numChars < 0) { TclNumUtfCharsM(numChars, objPtr->bytes, objPtr->length); stringPtr->numChars = numChars; } return numChars; } -size_t +Tcl_Size TclGetCharLength( Tcl_Obj *objPtr) /* The String object to get the num chars * of. */ { - size_t numChars = 0; + Tcl_Size numChars = 0; /* * Quick, no-shimmer return for short string reps. @@ -509,7 +509,7 @@ int TclCheckEmptyString( Tcl_Obj *objPtr) { - size_t length = TCL_INDEX_NONE; + Tcl_Size length = TCL_INDEX_NONE; if (objPtr->bytes == &tclEmptyString) { return TCL_EMPTYSTRING_YES; @@ -553,18 +553,22 @@ int Tcl_GetUniChar( Tcl_Obj *objPtr, /* The object to get the Unicode charater * from. */ - size_t index) /* Get the index'th Unicode character. */ + Tcl_Size index) /* Get the index'th Unicode character. */ { String *stringPtr; int ch; + if (index < 0) { + return -1; + } + /* * Optimize the case where we're really dealing with a ByteArray object * we don't need to convert to a string to perform the indexing operation. */ if (TclIsPureByteArray(objPtr)) { - size_t length = 0; + Tcl_Size length = 0; unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); if (index >= length) { return -1; @@ -622,17 +626,21 @@ int TclGetUniChar( Tcl_Obj *objPtr, /* The object to get the Unicode charater * from. */ - size_t index) /* Get the index'th Unicode character. */ + Tcl_Size index) /* Get the index'th Unicode character. */ { int ch = 0; + if (index < 0) { + return -1; + } + /* * Optimize the ByteArray case: N need need to convert to a string to * perform the indexing operation. */ if (TclIsPureByteArray(objPtr)) { - size_t length = 0; + Tcl_Size length = 0; unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); if (index >= length) { return -1; @@ -641,7 +649,7 @@ TclGetUniChar( return bytes[index]; } - size_t numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); + Tcl_Size numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); if (index >= numChars) { return -1; @@ -694,7 +702,7 @@ TclGetUnicodeFromObj( if (lengthPtr != NULL) { if (stringPtr->numChars > INT_MAX) { Tcl_Panic("Tcl_GetUnicodeFromObj with 'int' lengthPtr" - " cannot handle such long strings. Please use 'size_t'"); + " cannot handle such long strings. Please use 'Tcl_Size'"); } *lengthPtr = (int)stringPtr->numChars; } @@ -706,7 +714,7 @@ Tcl_UniChar * Tcl_GetUnicodeFromObj( Tcl_Obj *objPtr, /* The object to find the unicode string * for. */ - size_t *lengthPtr) /* If non-NULL, the location where the string + Tcl_Size *lengthPtr) /* If non-NULL, the location where the string * rep's unichar length should be stored. If * NULL, no length is stored. */ { @@ -749,14 +757,14 @@ Tcl_GetUnicodeFromObj( Tcl_Obj * Tcl_GetRange( Tcl_Obj *objPtr, /* The Tcl object to find the range of. */ - size_t first, /* First index of the range. */ - size_t last) /* Last index of the range. */ + Tcl_Size first, /* First index of the range. */ + Tcl_Size last) /* Last index of the range. */ { Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */ String *stringPtr; - size_t length = 0; + Tcl_Size length = 0; - if (first == TCL_INDEX_NONE) { + if (first < 0) { first = TCL_INDEX_START; } @@ -768,10 +776,10 @@ Tcl_GetRange( if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); - if (last >= length) { + if (last < 0 || last >= length) { last = length - 1; } - if (last + 1 < first + 1) { + if (last < first) { TclNewObj(newObjPtr); return newObjPtr; } @@ -794,10 +802,10 @@ Tcl_GetRange( TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length); } if (stringPtr->numChars == objPtr->length) { - if (last >= stringPtr->numChars) { + if (last < 0 || last >= stringPtr->numChars) { last = stringPtr->numChars - 1; } - if (last + 1 < first + 1) { + if (last < first) { TclNewObj(newObjPtr); return newObjPtr; } @@ -815,20 +823,20 @@ Tcl_GetRange( FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } - if (last >= stringPtr->numChars) { + if (last < 0 || last >= stringPtr->numChars) { last = stringPtr->numChars - 1; } - if (last + 1 < first + 1) { + if (last < first) { TclNewObj(newObjPtr); return newObjPtr; } #if TCL_UTF_MAX < 4 /* See: bug [11ae2be95dac9417] */ - if ((first + 1 > 1) && ((stringPtr->unicode[first] & 0xFC00) == 0xDC00) + if ((first > 0) && ((stringPtr->unicode[first] & 0xFC00) == 0xDC00) && ((stringPtr->unicode[first-1] & 0xFC00) == 0xD800)) { ++first; } - if ((last + 2 < stringPtr->numChars + 1) + if ((last + 1 < stringPtr->numChars) && ((stringPtr->unicode[last+1] & 0xFC00) == 0xDC00) && ((stringPtr->unicode[last] & 0xFC00) == 0xD800)) { ++last; @@ -840,13 +848,13 @@ Tcl_GetRange( Tcl_Obj * TclGetRange( Tcl_Obj *objPtr, /* The Tcl object to find the range of. */ - size_t first, /* First index of the range. */ - size_t last) /* Last index of the range. */ + Tcl_Size first, /* First index of the range. */ + Tcl_Size last) /* Last index of the range. */ { Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */ - size_t length = 0; + Tcl_Size length = 0; - if (first == TCL_INDEX_NONE) { + if (first < 0) { first = TCL_INDEX_START; } @@ -858,22 +866,22 @@ TclGetRange( if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); - if (last >= length) { + if (last < 0 || last >= length) { last = length - 1; } - if (last + 1 < first + 1) { + if (last < first) { TclNewObj(newObjPtr); return newObjPtr; } return Tcl_NewByteArrayObj(bytes + first, last - first + 1); } - size_t numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); + Tcl_Size numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); - if (last >= numChars) { + if (last < 0 || last >= numChars) { last = numChars - 1; } - if (last + 1 < first + 1) { + if (last < first) { TclNewObj(newObjPtr); return newObjPtr; } @@ -908,7 +916,7 @@ Tcl_SetStringObj( Tcl_Obj *objPtr, /* Object whose internal rep to init. */ const char *bytes, /* Points to the first of the length bytes * used to initialize the object. */ - size_t length) /* The number of bytes to copy from "bytes" + Tcl_Size length) /* The number of bytes to copy from "bytes" * when initializing the object. If -1, * use bytes up to the first NUL byte.*/ { @@ -960,12 +968,16 @@ void Tcl_SetObjLength( Tcl_Obj *objPtr, /* Pointer to object. This object must not * currently be shared. */ - size_t length) /* Number of bytes desired for string + Tcl_Size length) /* Number of bytes desired for string * representation of object, not including * terminating null byte. */ { String *stringPtr; + if (length < 0) { + Tcl_Panic("Tcl_SetObjLength: length requested is negative: " + "%" TCL_SIZE_MODIFIER "d (integer overflow?)", length); + } if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetObjLength"); } @@ -1051,12 +1063,17 @@ int Tcl_AttemptSetObjLength( Tcl_Obj *objPtr, /* Pointer to object. This object must not * currently be shared. */ - size_t length) /* Number of bytes desired for string + Tcl_Size length) /* Number of bytes desired for string * representation of object, not including * terminating null byte. */ { String *stringPtr; + if (length < 0) { + /* Negative lengths => most likely integer overflow */ + return 0; + } + if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength"); } @@ -1150,7 +1167,7 @@ Tcl_SetUnicodeObj( Tcl_Obj *objPtr, /* The object to set the string of. */ const Tcl_UniChar *unicode, /* The Unicode string used to initialize the * object. */ - size_t numChars) /* Number of characters in the Unicode + Tcl_Size numChars) /* Number of characters in the Unicode * string. */ { if (Tcl_IsShared(objPtr)) { @@ -1160,14 +1177,15 @@ Tcl_SetUnicodeObj( SetUnicodeObj(objPtr, unicode, numChars); } -static size_t +static Tcl_Size UnicodeLength( const Tcl_UniChar *unicode) { - size_t numChars = 0; + Tcl_Size numChars = 0; if (unicode) { - while ((numChars != TCL_INDEX_NONE) && (unicode[numChars] != 0)) { + /* TODO - is this overflow check really necessary? */ + while ((numChars >= 0) && (unicode[numChars] != 0)) { numChars++; } } @@ -1179,11 +1197,12 @@ SetUnicodeObj( Tcl_Obj *objPtr, /* The object to set the string of. */ const Tcl_UniChar *unicode, /* The Unicode string used to initialize the * object. */ - size_t numChars) /* Number of characters in unicode. */ + Tcl_Size numChars) /* Number of characters in the Unicode + * string. */ { String *stringPtr; - if (numChars == TCL_INDEX_NONE) { + if (numChars < 0) { numChars = UnicodeLength(unicode); } @@ -1228,20 +1247,20 @@ Tcl_AppendLimitedToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* Points to the bytes to append to the * object. */ - size_t length, /* The number of bytes available to be + Tcl_Size length, /* The number of bytes available to be * appended from "bytes". If -1, then * all bytes up to a NUL byte are available. */ - size_t limit, /* The maximum number of bytes to append to + Tcl_Size limit, /* The maximum number of bytes to append to * the object. */ const char *ellipsis) /* Ellipsis marker string, appended to the * object to indicate not all available bytes * at "bytes" were appended. */ { String *stringPtr; - size_t toCopy = 0; - size_t eLen = 0; + Tcl_Size toCopy = 0; + Tcl_Size eLen = 0; - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = (bytes ? strlen(bytes) : 0); } if (length == 0) { @@ -1324,11 +1343,11 @@ Tcl_AppendToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* Points to the bytes to append to the * object. */ - size_t length) /* The number of bytes to append from "bytes". + Tcl_Size length) /* The number of bytes to append from "bytes". * If TCL_INDEX_NONE, then append all bytes up to NUL * byte. */ { - Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_INDEX_NONE, NULL); + Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_SIZE_MAX, NULL); } /* @@ -1337,7 +1356,7 @@ Tcl_AppendToObj( * Tcl_AppendUnicodeToObj -- * * This function appends a Unicode string to an object in the most - * efficient manner possible. Length must be >= 0. + * efficient manner possible. * * Results: * None. @@ -1353,7 +1372,8 @@ Tcl_AppendUnicodeToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* The Unicode string to append to the * object. */ - size_t length) /* Number of chars in unicode. */ + Tcl_Size length) /* Number of chars in Unicode. Negative + * lengths means nul terminated */ { String *stringPtr; @@ -1407,8 +1427,8 @@ Tcl_AppendObjToObj( Tcl_Obj *appendObjPtr) /* Object to append. */ { String *stringPtr; - size_t length = 0, numChars; - size_t appendNumChars = TCL_INDEX_NONE; + Tcl_Size length = 0, numChars; + Tcl_Size appendNumChars = TCL_INDEX_NONE; const char *bytes; /* @@ -1448,7 +1468,7 @@ Tcl_AppendObjToObj( * First, get the lengths. */ - size_t lengthSrc = 0; + Tcl_Size lengthSrc = 0; (void) Tcl_GetByteArrayFromObj(objPtr, &length); (void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc); @@ -1471,7 +1491,7 @@ Tcl_AppendObjToObj( */ TclAppendBytesToByteArray(objPtr, - Tcl_GetByteArrayFromObj(appendObjPtr, (size_t *)NULL), lengthSrc); + Tcl_GetByteArrayFromObj(appendObjPtr, (Tcl_Size *) NULL), lengthSrc); return; } @@ -1520,7 +1540,7 @@ Tcl_AppendObjToObj( bytes = Tcl_GetStringFromObj(appendObjPtr, &length); numChars = stringPtr->numChars; - if ((numChars != TCL_INDEX_NONE) && TclHasInternalRep(appendObjPtr, &tclStringType)) { + if ((numChars >= 0) && TclHasInternalRep(appendObjPtr, &tclStringType)) { String *appendStringPtr = GET_STRING(appendObjPtr); appendNumChars = appendStringPtr->numChars; @@ -1528,7 +1548,7 @@ Tcl_AppendObjToObj( AppendUtfToUtfRep(objPtr, bytes, length); - if ((numChars != TCL_INDEX_NONE) && (appendNumChars != TCL_INDEX_NONE)) { + if ((numChars >= 0) && (appendNumChars >= 0)) { stringPtr->numChars = numChars + appendNumChars; } } @@ -1554,12 +1574,12 @@ static void AppendUnicodeToUnicodeRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* String to append. */ - size_t appendNumChars) /* Number of chars of "unicode" to append. */ + Tcl_Size appendNumChars) /* Number of chars of "unicode" to append. */ { String *stringPtr; - size_t numChars; + Tcl_Size numChars; - if (appendNumChars == TCL_INDEX_NONE) { + if (appendNumChars < 0) { appendNumChars = UnicodeLength(unicode); } if (appendNumChars == 0) { @@ -1580,7 +1600,7 @@ AppendUnicodeToUnicodeRep( numChars = stringPtr->numChars + appendNumChars; if (numChars > stringPtr->maxChars) { - size_t index = TCL_INDEX_NONE; + Tcl_Size offset = -1; /* * Protect against case where Unicode points into the existing @@ -1590,7 +1610,7 @@ AppendUnicodeToUnicodeRep( if (unicode && unicode >= stringPtr->unicode && unicode <= stringPtr->unicode + stringPtr->maxChars) { - index = unicode - stringPtr->unicode; + offset = unicode - stringPtr->unicode; } GrowUnicodeBuffer(objPtr, numChars); @@ -1600,8 +1620,8 @@ AppendUnicodeToUnicodeRep( * Relocate Unicode if needed; see above. */ - if (index != TCL_INDEX_NONE) { - unicode = stringPtr->unicode + index; + if (offset >= 0) { + unicode = stringPtr->unicode + offset; } } @@ -1642,7 +1662,7 @@ static void AppendUnicodeToUtfRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* String to convert to UTF. */ - size_t numChars) /* Number of chars of unicode to convert. */ + Tcl_Size numChars) /* Number of chars of Unicode to convert. */ { String *stringPtr = GET_STRING(objPtr); @@ -1675,7 +1695,7 @@ static void AppendUtfToUnicodeRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* String to convert to Unicode. */ - size_t numBytes) /* Number of bytes of "bytes" to convert. */ + Tcl_Size numBytes) /* Number of bytes of "bytes" to convert. */ { String *stringPtr; @@ -1683,7 +1703,7 @@ AppendUtfToUnicodeRep( return; } - ExtendUnicodeRepWithString(objPtr, bytes, numBytes, TCL_INDEX_NONE); + ExtendUnicodeRepWithString(objPtr, bytes, numBytes, -1); TclInvalidateStringRep(objPtr); stringPtr = GET_STRING(objPtr); stringPtr->allocated = 0; @@ -1711,10 +1731,10 @@ static void AppendUtfToUtfRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* String to append. */ - size_t numBytes) /* Number of bytes of "bytes" to append. */ + Tcl_Size numBytes) /* Number of bytes of "bytes" to append. */ { String *stringPtr; - size_t newLength, oldLength; + Tcl_Size newLength, oldLength; if (numBytes == 0) { return; @@ -1729,11 +1749,14 @@ AppendUtfToUtfRep( objPtr->length = 0; } oldLength = objPtr->length; + if (numBytes > TCL_SIZE_MAX - oldLength) { + Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX); + } newLength = numBytes + oldLength; stringPtr = GET_STRING(objPtr); if (newLength > stringPtr->allocated) { - size_t offset = TCL_INDEX_NONE; + Tcl_Size offset = -1; /* * Protect against case where unicode points into the existing @@ -1757,7 +1780,7 @@ AppendUtfToUtfRep( * Relocate bytes if needed; see above. */ - if (offset != TCL_INDEX_NONE) { + if (offset >= 0) { bytes = objPtr->bytes + offset; } } @@ -1766,7 +1789,7 @@ AppendUtfToUtfRep( * Invalidate the unicode data. */ - stringPtr->numChars = TCL_INDEX_NONE; + stringPtr->numChars = -1; stringPtr->hasUnicode = 0; if (bytes) { @@ -1812,7 +1835,7 @@ Tcl_AppendStringsToObj( if (bytes == NULL) { break; } - Tcl_AppendToObj(objPtr, bytes, TCL_INDEX_NONE); + Tcl_AppendToObj(objPtr, bytes, -1); } va_end(argList); } @@ -1842,12 +1865,12 @@ Tcl_AppendFormatToObj( Tcl_Interp *interp, Tcl_Obj *appendObj, const char *format, - size_t objc, + Tcl_Size objc, Tcl_Obj *const objv[]) { const char *span = format, *msg, *errCode; int gotXpg = 0, gotSequential = 0; - size_t objIndex = 0, originalLength, limit, numBytes = 0; + Tcl_Size objIndex = 0, originalLength, limit, numBytes = 0; Tcl_UniChar ch = 0; static const char *mixedXPG = "cannot mix \"%\" and \"%n$\" conversion specifiers"; @@ -1861,7 +1884,7 @@ Tcl_AppendFormatToObj( Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj"); } (void)Tcl_GetStringFromObj(appendObj, &originalLength); - limit = (size_t)INT_MAX - originalLength; + limit = TCL_SIZE_MAX - originalLength; /* * Format string is NUL-terminated. @@ -1870,12 +1893,13 @@ Tcl_AppendFormatToObj( while (*format != '\0') { char *end; int gotMinus = 0, gotHash = 0, gotZero = 0, gotSpace = 0, gotPlus = 0; - int width, gotPrecision, precision, sawFlag, useShort = 0, useBig = 0; + int gotPrecision, sawFlag, useShort = 0, useBig = 0; + Tcl_Size width, precision; #ifndef TCL_WIDE_INT_IS_LONG int useWide = 0; #endif - int newXpg, numChars, allocSegment = 0, segmentLimit; - size_t segmentNumBytes; + int newXpg, allocSegment = 0; + Tcl_Size numChars, segmentLimit, segmentNumBytes; Tcl_Obj *segment; int step = TclUtfToUniChar(format, &ch); @@ -1939,7 +1963,7 @@ Tcl_AppendFormatToObj( } gotSequential = 1; } - if (objIndex >= objc) { + if (objIndex < 0 || objIndex >= objc) { msg = badIndex[gotXpg]; errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; @@ -1996,7 +2020,7 @@ Tcl_AppendFormatToObj( errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } - if (TclGetIntFromObj(interp, objv[objIndex], &width) != TCL_OK) { + if (TclGetSizeIntFromObj(interp, objv[objIndex], &width) != TCL_OK) { goto error; } if (width < 0) { @@ -2007,7 +2031,7 @@ Tcl_AppendFormatToObj( format += step; step = TclUtfToUniChar(format, &ch); } - if (width > (int) limit) { + if (width > limit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; @@ -2033,7 +2057,7 @@ Tcl_AppendFormatToObj( errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } - if (TclGetIntFromObj(interp, objv[objIndex], &precision) + if (TclGetSizeIntFromObj(interp, objv[objIndex], &precision) != TCL_OK) { goto error; } @@ -2159,7 +2183,8 @@ Tcl_AppendFormatToObj( long l; Tcl_WideInt w; mp_int big; - int toAppend, isNegative = 0; + int isNegative = 0; + Tcl_Size toAppend; #ifndef TCL_WIDE_INT_IS_LONG if (ch == 'p') { @@ -2217,7 +2242,7 @@ Tcl_AppendFormatToObj( TclNewObj(segment); allocSegment = 1; - segmentLimit = INT_MAX; + segmentLimit = TCL_SIZE_MAX; Tcl_IncrRefCount(segment); if ((isNegative || gotPlus || gotSpace) && (useBig || ch=='d')) { @@ -2247,7 +2272,7 @@ Tcl_AppendFormatToObj( switch (ch) { case 'd': { - size_t length; + Tcl_Size length; Tcl_Obj *pure; const char *bytes; @@ -2282,10 +2307,10 @@ Tcl_AppendFormatToObj( */ if (gotPrecision) { - if (length < (size_t)precision) { + if (length < precision) { segmentLimit -= precision - length; } - while (length < (size_t)precision) { + while (length < precision) { Tcl_AppendToObj(segment, "0", 1); length++; } @@ -2293,10 +2318,10 @@ Tcl_AppendFormatToObj( } if (gotZero) { length += Tcl_GetCharLength(segment); - if (length < (size_t)width) { + if (length < width) { segmentLimit -= width - length; } - while (length < (size_t)width) { + while (length < width) { Tcl_AppendToObj(segment, "0", 1); length++; } @@ -2320,7 +2345,7 @@ Tcl_AppendFormatToObj( Tcl_WideUInt bits = 0; Tcl_WideInt numDigits = 0; int numBits = 4, base = 16, index = 0, shift = 0; - size_t length; + Tcl_Size length; Tcl_Obj *pure; char *bytes; @@ -2414,10 +2439,10 @@ Tcl_AppendFormatToObj( mp_clear(&big); } if (gotPrecision) { - if (length < (size_t)precision) { + if (length < precision) { segmentLimit -= precision - length; } - while (length < (size_t)precision) { + while (length < precision) { Tcl_AppendToObj(segment, "0", 1); length++; } @@ -2425,10 +2450,10 @@ Tcl_AppendFormatToObj( } if (gotZero) { length += Tcl_GetCharLength(segment); - if (length < (size_t)width) { + if (length < width) { segmentLimit -= width - length; } - while (length < (size_t)width) { + while (length < width) { Tcl_AppendToObj(segment, "0", 1); length++; } @@ -2481,15 +2506,17 @@ Tcl_AppendFormatToObj( *p++ = '+'; } if (width) { - p += snprintf(p, TCL_INTEGER_SPACE, "%d", width); + p += snprintf( + p, TCL_INTEGER_SPACE, "%" TCL_SIZE_MODIFIER "d", width); if (width > length) { length = width; } } if (gotPrecision) { *p++ = '.'; - p += snprintf(p, TCL_INTEGER_SPACE, "%d", precision); - if (precision > INT_MAX - length) { + p += snprintf( + p, TCL_INTEGER_SPACE, "%" TCL_SIZE_MODIFIER "d", precision); + if (precision > TCL_SIZE_MAX - length) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; @@ -2512,7 +2539,7 @@ Tcl_AppendFormatToObj( goto errorMsg; } bytes = TclGetString(segment); - if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) { + if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; @@ -2588,7 +2615,7 @@ Tcl_AppendFormatToObj( errorMsg: if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, TCL_INDEX_NONE)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, NULL); } error: @@ -2614,7 +2641,7 @@ Tcl_Obj * Tcl_Format( Tcl_Interp *interp, const char *format, - size_t objc, + Tcl_Size objc, Tcl_Obj *const objv[]) { int result; @@ -2648,7 +2675,7 @@ AppendPrintfToObjVA( va_list argList) { int code; - size_t objc; + Tcl_Size objc; Tcl_Obj **objv, *list; const char *p; @@ -2895,7 +2922,7 @@ Tcl_ObjPrintf( char * TclGetStringStorage( Tcl_Obj *objPtr, - size_t *sizePtr) + Tcl_Size *sizePtr) { String *stringPtr; @@ -2929,14 +2956,16 @@ Tcl_Obj * TclStringRepeat( Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t count, + Tcl_Size count, int flags) { Tcl_Obj *objResultPtr; int inPlace = flags & TCL_STRING_IN_PLACE; - size_t length = 0, unichar = 0, done = 1; + Tcl_Size length = 0; + int unichar = 0; + Tcl_Size done = 1; int binary = TclIsPureByteArray(objPtr); - size_t maxCount; + Tcl_Size maxCount; /* assert (count >= 2) */ @@ -2959,15 +2988,15 @@ TclStringRepeat( if (binary) { /* Result will be pure byte array. Pre-size it */ (void)Tcl_GetByteArrayFromObj(objPtr, &length); - maxCount = TCL_SIZE_SMAX; + maxCount = TCL_SIZE_MAX; } else if (unichar) { /* Result will be pure Tcl_UniChar array. Pre-size it. */ (void)Tcl_GetUnicodeFromObj(objPtr, &length); - maxCount = TCL_SIZE_SMAX/sizeof(Tcl_UniChar); + maxCount = TCL_SIZE_MAX/sizeof(Tcl_UniChar); } else { /* Result will be concat of string reps. Pre-size it. */ (void)Tcl_GetStringFromObj(objPtr, &length); - maxCount = TCL_SIZE_SMAX; + maxCount = TCL_SIZE_MAX; } if (length == 0) { @@ -2980,9 +3009,9 @@ TclStringRepeat( if (interp) { Tcl_SetObjResult( interp, - Tcl_ObjPrintf("max size for a Tcl value (%" TCL_Z_MODIFIER - "u bytes) exceeded", - TCL_SIZE_SMAX)); + Tcl_ObjPrintf("max size for a Tcl value (%" TCL_SIZE_MODIFIER + "d bytes) exceeded", + TCL_SIZE_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return NULL; @@ -3001,7 +3030,7 @@ TclStringRepeat( done *= 2; } TclAppendBytesToByteArray(objResultPtr, - Tcl_GetByteArrayFromObj(objResultPtr, (size_t *)NULL), + Tcl_GetByteArrayFromObj(objResultPtr, (Tcl_Size *) NULL), (count - done) * length); } else if (unichar) { /* @@ -3015,11 +3044,12 @@ TclStringRepeat( objResultPtr = objPtr; } + /* TODO - overflow check */ if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "string size overflow: unable to alloc %" - TCL_Z_MODIFIER "u bytes", + TCL_SIZE_MODIFIER "d bytes", STRING_SIZE(count*length))); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } @@ -3043,10 +3073,11 @@ TclStringRepeat( TclFreeInternalRep(objPtr); objResultPtr = objPtr; } + /* TODO - overflow check */ if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "string size overflow: unable to alloc %" TCL_Z_MODIFIER "u bytes", + "string size overflow: unable to alloc %" TCL_SIZE_MODIFIER "d bytes", count*length)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } @@ -3090,7 +3121,7 @@ TclStringCat( { Tcl_Obj *objResultPtr, * const *ov; int oc, binary = 1; - size_t length = 0; + Tcl_Size 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 */ @@ -3152,7 +3183,7 @@ TclStringCat( * Result will be pure byte array. Pre-size it */ - size_t numBytes = 0; + Tcl_Size numBytes = 0; ov = objv; oc = objc; do { @@ -3172,7 +3203,7 @@ TclStringCat( if (length == 0) { first = last; } - if (length > (TCL_SIZE_SMAX-numBytes)) { + if (length > (TCL_SIZE_MAX-numBytes)) { goto overflow; } length += numBytes; @@ -3190,7 +3221,7 @@ TclStringCat( Tcl_Obj *objPtr = *ov++; if ((objPtr->bytes == NULL) || (objPtr->length)) { - size_t numChars; + Tcl_Size numChars; (void)Tcl_GetUnicodeFromObj(objPtr, &numChars); /* PANIC? */ if (numChars) { @@ -3198,7 +3229,7 @@ TclStringCat( if (length == 0) { first = last; } - if (length > ((TCL_SIZE_SMAX/sizeof(Tcl_UniChar))-numChars)) { + if (length > (Tcl_Size) ((TCL_SIZE_MAX/sizeof(Tcl_UniChar))-numChars)) { goto overflow; } length += numChars; @@ -3240,7 +3271,7 @@ TclStringCat( first = last = objc - oc - 1; if (oc && (length == 0)) { - size_t numBytes; + Tcl_Size numBytes; /* assert ( pendingPtr != NULL ) */ @@ -3265,7 +3296,7 @@ TclStringCat( if (numBytes) { first = last; } - } else if (numBytes > (TCL_SIZE_SMAX - length)) { + } else if (numBytes > (TCL_SIZE_MAX - length)) { goto overflow; } length += numBytes; @@ -3273,7 +3304,7 @@ TclStringCat( } while (oc && (length == 0)); while (oc) { - size_t numBytes; + Tcl_Size numBytes; Tcl_Obj *objPtr = *ov++; /* assert ( length > 0 && pendingPtr == NULL ) */ @@ -3282,7 +3313,7 @@ TclStringCat( numBytes = objPtr->length; if (numBytes) { last = objc - oc; - if (numBytes > (TCL_SIZE_SMAX - length)) { + if (numBytes > (TCL_SIZE_MAX - length)) { goto overflow; } length += numBytes; @@ -3309,7 +3340,7 @@ TclStringCat( */ if (inPlace && !Tcl_IsShared(*objv)) { - size_t start = 0; + Tcl_Size start = 0; objResultPtr = *objv++; objc--; (void)Tcl_GetByteArrayFromObj(objResultPtr, &start); @@ -3328,7 +3359,7 @@ TclStringCat( */ if (TclIsPureByteArray(objPtr)) { - size_t more = 0; + Tcl_Size more = 0; unsigned char *src = Tcl_GetByteArrayFromObj(objPtr, &more); memcpy(dst, src, more); dst += more; @@ -3339,7 +3370,7 @@ TclStringCat( Tcl_UniChar *dst; if (inPlace && !Tcl_IsShared(*objv)) { - size_t start; + Tcl_Size start; objResultPtr = *objv++; objc--; @@ -3379,7 +3410,7 @@ TclStringCat( Tcl_Obj *objPtr = *objv++; if ((objPtr->bytes == NULL) || (objPtr->length)) { - size_t more; + Tcl_Size more; Tcl_UniChar *src = Tcl_GetUnicodeFromObj(objPtr, &more); memcpy(dst, src, more * sizeof(Tcl_UniChar)); dst += more; @@ -3390,7 +3421,7 @@ TclStringCat( char *dst; if (inPlace && !Tcl_IsShared(*objv)) { - size_t start; + Tcl_Size start; objResultPtr = *objv++; objc--; @@ -3426,7 +3457,7 @@ TclStringCat( Tcl_Obj *objPtr = *objv++; if ((objPtr->bytes == NULL) || (objPtr->length)) { - size_t more; + Tcl_Size more; char *src = Tcl_GetStringFromObj(objPtr, &more); memcpy(dst, src, more); @@ -3441,7 +3472,7 @@ TclStringCat( overflow: if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max size for a Tcl value (%" TCL_Z_MODIFIER "u bytes) exceeded", TCL_SIZE_SMAX)); + "max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return NULL; @@ -3469,12 +3500,12 @@ TclStringCmp( Tcl_Obj *value2Ptr, int checkEq, /* comparison is only for equality */ int nocase, /* comparison is not case sensitive */ - size_t reqlength) /* requested length in characters; + Tcl_Size reqlength) /* requested length in characters; * TCL_INDEX_NONE to compare whole strings */ { const char *s1, *s2; int empty, match; - size_t length, s1len = 0, s2len = 0; + Tcl_Size length, s1len = 0, s2len = 0; memCmpFn_t memCmpFn; if ((reqlength == 0) || (value1Ptr == value2Ptr)) { @@ -3663,14 +3694,14 @@ Tcl_Obj * TclStringFirst( Tcl_Obj *needle, Tcl_Obj *haystack, - size_t start) + Tcl_Size start) { - size_t lh = 0, ln = Tcl_GetCharLength(needle); - size_t value = TCL_INDEX_NONE; + Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle); + Tcl_Size value = -1; Tcl_UniChar *checkStr, *endStr, *uh, *un; Tcl_Obj *obj; - if (start == TCL_INDEX_NONE) { + if (start < 0) { start = 0; } if (ln == 0) { @@ -3770,10 +3801,10 @@ Tcl_Obj * TclStringLast( Tcl_Obj *needle, Tcl_Obj *haystack, - size_t last) + Tcl_Size last) { - size_t lh = 0, ln = Tcl_GetCharLength(needle); - size_t value = TCL_INDEX_NONE; + Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle); + Tcl_Size value = -1; Tcl_UniChar *checkStr, *uh, *un; Tcl_Obj *obj; @@ -3791,7 +3822,7 @@ TclStringLast( unsigned char *check, *bh = Tcl_GetByteArrayFromObj(haystack, &lh); unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); - if (last + 1 >= lh + 1) { + if (last >= lh) { last = lh - 1; } if (last + 1 < ln) { @@ -3814,7 +3845,7 @@ TclStringLast( uh = Tcl_GetUnicodeFromObj(haystack, &lh); un = Tcl_GetUnicodeFromObj(needle, &ln); - if (last + 1 >= lh + 1) { + if (last >= lh) { last = lh - 1; } if (last + 1 < ln) { @@ -3857,7 +3888,7 @@ static void ReverseBytes( unsigned char *to, /* Copy bytes into here... */ unsigned char *from, /* ...from here... */ - size_t count) /* Until this many are copied, */ + Tcl_Size count) /* Until this many are copied, */ /* reversing as you go. */ { unsigned char *src = from + count; @@ -3890,13 +3921,13 @@ TclStringReverse( #endif if (TclIsPureByteArray(objPtr)) { - size_t numBytes = 0; + Tcl_Size numBytes = 0; unsigned char *from = Tcl_GetByteArrayFromObj(objPtr, &numBytes); if (!inPlace || Tcl_IsShared(objPtr)) { objPtr = Tcl_NewByteArrayObj(NULL, numBytes); } - ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, (size_t *)NULL), from, numBytes); + ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)NULL), from, numBytes); return objPtr; } @@ -3971,8 +4002,8 @@ TclStringReverse( } if (objPtr->bytes) { - size_t numChars = stringPtr->numChars; - size_t numBytes = objPtr->length; + Tcl_Size numChars = stringPtr->numChars; + Tcl_Size numBytes = objPtr->length; char *to, *from = objPtr->bytes; if (!inPlace || Tcl_IsShared(objPtr)) { @@ -3981,7 +4012,7 @@ TclStringReverse( } to = objPtr->bytes; - if ((numChars == TCL_INDEX_NONE) || (numChars < numBytes)) { + if (numChars < numBytes) { /* * Either numChars == -1 and we don't know how many chars are * represented by objPtr->bytes and we need Pass 1 just in case, @@ -3991,7 +4022,7 @@ TclStringReverse( * Pass 1. Reverse the bytes of each multi-byte character. */ - size_t bytesLeft = numBytes; + Tcl_Size bytesLeft = numBytes; int chw; while (bytesLeft) { @@ -4001,7 +4032,7 @@ TclStringReverse( * skip calling Tcl_UtfCharComplete() here. */ - size_t bytesInChar = TclUtfToUCS4(from, &chw); + int bytesInChar = TclUtfToUCS4(from, &chw); ReverseBytes((unsigned char *)to, (unsigned char *)from, bytesInChar); @@ -4049,8 +4080,8 @@ Tcl_Obj * TclStringReplace( Tcl_Interp *interp, /* For error reporting, may be NULL */ Tcl_Obj *objPtr, /* String to act upon */ - size_t first, /* First index to replace */ - size_t count, /* How many chars to replace */ + Tcl_Size first, /* First index to replace */ + Tcl_Size count, /* How many chars to replace */ Tcl_Obj *insertPtr, /* Replacement string, may be NULL */ int flags) /* TCL_STRING_IN_PLACE => attempt in-place */ { @@ -4058,13 +4089,16 @@ TclStringReplace( Tcl_Obj *result; /* Replace nothing with nothing */ - if ((insertPtr == NULL) && (count == 0)) { + if ((insertPtr == NULL) && (count <= 0)) { if (inPlace) { return objPtr; } else { return Tcl_DuplicateObj(objPtr); } } + if (first < 0) { + first = 0; + } /* * The caller very likely had to call Tcl_GetCharLength() or similar @@ -4074,7 +4108,7 @@ TclStringReplace( */ if (TclIsPureByteArray(objPtr)) { - size_t numBytes = 0; + Tcl_Size numBytes = 0; unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &numBytes); if (insertPtr == NULL) { @@ -4097,7 +4131,7 @@ TclStringReplace( } if (TclIsPureByteArray(insertPtr)) { - size_t newBytes = 0; + Tcl_Size newBytes = 0; unsigned char *iBytes = Tcl_GetByteArrayFromObj(insertPtr, &newBytes); @@ -4112,11 +4146,11 @@ TclStringReplace( return objPtr; } - if (newBytes > (TCL_SIZE_SMAX - (numBytes - count))) { + if (newBytes > (TCL_SIZE_MAX - (numBytes - count))) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max size for a Tcl value (%" TCL_Z_MODIFIER "u bytes) exceeded", - TCL_SIZE_SMAX)); + "max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", + TCL_SIZE_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return NULL; @@ -4142,7 +4176,7 @@ TclStringReplace( /* The traditional implementation... */ { - size_t numChars; + Tcl_Size numChars; Tcl_UniChar *ustring = Tcl_GetUnicodeFromObj(objPtr, &numChars); /* TODO: Is there an in-place option worth pursuing here? */ @@ -4192,11 +4226,11 @@ static void ExtendUnicodeRepWithString( Tcl_Obj *objPtr, const char *bytes, - size_t numBytes, - size_t numAppendChars) + Tcl_Size numBytes, + Tcl_Size numAppendChars) { String *stringPtr = GET_STRING(objPtr); - size_t needed, numOrigChars = 0; + Tcl_Size needed, numOrigChars = 0; Tcl_UniChar *dst, unichar = 0; if (stringPtr->hasUnicode) { @@ -4394,21 +4428,21 @@ UpdateStringOfString( } } -static size_t +static Tcl_Size ExtendStringRepWithUnicode( Tcl_Obj *objPtr, const Tcl_UniChar *unicode, - size_t numChars) + Tcl_Size numChars) { /* * Precondition: this is the "string" Tcl_ObjType. */ - size_t i, origLength, size = 0; + Tcl_Size i, origLength, size = 0; char *dst; String *stringPtr = GET_STRING(objPtr); - if (numChars == TCL_INDEX_NONE) { + if (numChars < 0) { numChars = UnicodeLength(unicode); } @@ -4425,14 +4459,18 @@ ExtendStringRepWithUnicode( * Quick cheap check in case we have more than enough room. */ - if (numChars <= (INT_MAX - size)/TCL_UTF_MAX + if (numChars <= (TCL_SIZE_MAX - size)/TCL_UTF_MAX && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) { goto copyBytes; } - for (i = 0; i < numChars; i++) { + for (i = 0; i < numChars && size >= 0; i++) { + /* TODO - overflow check! I don't think check below at end suffices */ size += TclUtfCount(unicode[i]); } + if (size < 0) { + Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX); + } /* * Grow space if needed. |