From 411fc46d4f5e5e93a7d69db7f50e42b53005e343 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 8 Nov 2021 00:06:27 +0000 Subject: [9899c273ab] Rewrite Tcl_InitStringRep to account for all encounters with the non-allocated empty string rep. --- generic/tclBinary.c | 1 - generic/tclDictObj.c | 1 + generic/tclInt.h | 3 ++- generic/tclObj.c | 51 +++++++++++++++++++++++++++++++++------------------ 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/generic/tclBinary.c b/generic/tclBinary.c index 5eb5b54..a586f18 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -842,7 +842,6 @@ UpdateStringOfByteArray( for (i = 0; i < length; i++) { dst += Tcl_UniCharToUtf(src[i], dst); } - (void) Tcl_InitStringRep(objPtr, NULL, size); } } diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index 900974f..b4249b8 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -566,6 +566,7 @@ UpdateStringOfDict( dst += TclConvertElement(elem, length, dst, flagPtr[i+1]); *dst++ = ' '; } + /* Last space overwrote the terminating NUL; cal T_ISR again to restore */ (void)Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1); if (flagPtr != localFlags) { diff --git a/generic/tclInt.h b/generic/tclInt.h index 03d005a..7b03502 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4492,7 +4492,8 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, * must point to a location from which "len" bytes may be read. These * constraints are not checked here. The validity of the bytes copied * as a value string representation is also not verififed. This macro - * must not be called while "objPtr" is being freed. The caller must use + * must not be called while "objPtr" is being freed or when "objPtr" + * already has a string representation. The caller must use * this macro properly. Improper use can lead to dangerous results. * Because "len" is referenced multiple times, take care that it is an * expression with the same value each use. diff --git a/generic/tclObj.c b/generic/tclObj.c index e5ec838..92c6655 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -1815,32 +1815,48 @@ Tcl_InitStringRep( Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } - /* Allocate */ if (objPtr->bytes == NULL) { - /* Allocate only as empty - extend later if bytes copied */ - objPtr->length = 0; - if (numBytes) { + /* Start with no string rep */ + if (numBytes == 0) { + TclInitStringRep(objPtr, NULL, 0); + return objPtr->bytes; + } else { objPtr->bytes = (char *)attemptckalloc(numBytes + 1); - if (objPtr->bytes == NULL) { - return NULL; - } - if (bytes) { - /* Copy */ - memcpy(objPtr->bytes, bytes, numBytes); + if (objPtr->bytes) { objPtr->length = (int) numBytes; + if (bytes) { + memcpy(objPtr->bytes, bytes, numBytes); + } + objPtr->bytes[objPtr->length] = '\0'; } + } + } else if (objPtr->bytes == &tclEmptyString) { + /* Start with empty string rep (not allocated) */ + if (numBytes == 0) { + return objPtr->bytes; } else { - TclInitStringRep(objPtr, NULL, 0); + objPtr->bytes = (char *)attemptckalloc(numBytes + 1); + if (objPtr->bytes) { + objPtr->length = (int) numBytes; + objPtr->bytes[objPtr->length] = '\0'; + } } } else { - /* objPtr->bytes != NULL bytes == NULL - Truncate */ - objPtr->bytes = (char *)ckrealloc(objPtr->bytes, numBytes + 1); - objPtr->length = (int)numBytes; + /* Start with non-empty string rep (allocated) */ + if (numBytes == 0) { + ckfree(objPtr->bytes); + TclInitStringRep(objPtr, NULL, 0); + return objPtr->bytes; + } else { + objPtr->bytes = (char *)attemptckrealloc(objPtr->bytes, + numBytes + 1); + if (objPtr->bytes) { + objPtr->length = (int) numBytes; + objPtr->bytes[objPtr->length] = '\0'; + } + } } - /* Terminate */ - objPtr->bytes[objPtr->length] = '\0'; - return objPtr->bytes; } @@ -3517,7 +3533,6 @@ UpdateStringOfBignum( if (MP_OKAY != mp_to_radix(&bignumVal, stringVal, size, NULL, 10)) { Tcl_Panic("conversion failure in UpdateStringOfBignum"); } - (void) Tcl_InitStringRep(objPtr, NULL, size - 1); } /* -- cgit v0.12