summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2021-11-08 00:06:27 (GMT)
committerdgp <dgp@users.sourceforge.net>2021-11-08 00:06:27 (GMT)
commit411fc46d4f5e5e93a7d69db7f50e42b53005e343 (patch)
tree225af54f823864e3d85cd793e586d141337cfee1 /generic
parenta112105294460f178a371ba9116b11c263b29f00 (diff)
downloadtcl-411fc46d4f5e5e93a7d69db7f50e42b53005e343.zip
tcl-411fc46d4f5e5e93a7d69db7f50e42b53005e343.tar.gz
tcl-411fc46d4f5e5e93a7d69db7f50e42b53005e343.tar.bz2
[9899c273ab] Rewrite Tcl_InitStringRep to account for all encounters with
the non-allocated empty string rep.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclBinary.c1
-rw-r--r--generic/tclDictObj.c1
-rw-r--r--generic/tclInt.h3
-rw-r--r--generic/tclObj.c51
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);
}
/*