summaryrefslogtreecommitdiffstats
path: root/generic/tclListObj.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2011-05-10 16:52:35 (GMT)
committerdgp <dgp@users.sourceforge.net>2011-05-10 16:52:35 (GMT)
commitd8668e5c5d98e9b11f6c85e8bd3c7c6ac6834838 (patch)
treef83cbc6f986fb625947631c42b0f9c3930475634 /generic/tclListObj.c
parenta4456778c8605e05c3598b6848b2660ae7b10d27 (diff)
parentf9dece7738d140a66ebb5d47ee85c4d57249258a (diff)
downloadtcl-d8668e5c5d98e9b11f6c85e8bd3c7c6ac6834838.zip
tcl-d8668e5c5d98e9b11f6c85e8bd3c7c6ac6834838.tar.gz
tcl-d8668e5c5d98e9b11f6c85e8bd3c7c6ac6834838.tar.bz2
New internal routines TclScanElement() and TclConvertElement().
Rewritten guts of machinery to produce string rep of lists. [Bug 3173086]
Diffstat (limited to 'generic/tclListObj.c')
-rw-r--r--generic/tclListObj.c65
1 files changed, 31 insertions, 34 deletions
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index c2e9c78..17aa256 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -1806,19 +1806,29 @@ UpdateStringOfList(
Tcl_Obj *listPtr) /* List object with string rep to update. */
{
# define LOCAL_SIZE 20
- int localFlags[LOCAL_SIZE], *flagPtr;
+ int localFlags[LOCAL_SIZE], *flagPtr = NULL;
List *listRepPtr = ListRepPtr(listPtr);
int numElems = listRepPtr->elemCount;
- register int i;
+ int i, length, bytesNeeded = 0;
char *elem, *dst;
- int length;
Tcl_Obj **elemPtrs;
/*
- * Convert each element of the list to string form and then convert it to
- * proper list element form, adding it to the result buffer.
+ * Mark the list as being canonical; although it will now have a string
+ * rep, it is one we derived through proper "canonical" quoting and so
+ * it's known to be free from nasties relating to [concat] and [eval].
*/
+ listRepPtr->canonicalFlag = 1;
+
+ /* Handle empty list case first, so rest of the routine is simpler */
+
+ if (numElems == 0) {
+ listPtr->bytes = tclEmptyStringRep;
+ listPtr->length = 0;
+ return;
+ }
+
/*
* Pass 1: estimate space, gather flags.
*/
@@ -1826,54 +1836,41 @@ UpdateStringOfList(
if (numElems <= LOCAL_SIZE) {
flagPtr = localFlags;
} else {
+ /* We know numElems <= LIST_MAX, so this is safe. */
flagPtr = (int *) ckalloc((unsigned) numElems * sizeof(int));
}
- listPtr->length = 1;
elemPtrs = &listRepPtr->elements;
for (i = 0; i < numElems; i++) {
+ flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 );
elem = TclGetStringFromObj(elemPtrs[i], &length);
- listPtr->length += Tcl_ScanCountedElement(elem, length, flagPtr+i)+1;
-
- /*
- * Check for continued sanity. [Bug 1267380]
- */
-
- if (listPtr->length < 1) {
- Tcl_Panic("string representation size exceeds sane bounds");
+ bytesNeeded += TclScanElement(elem, length, flagPtr+i);
+ if (bytesNeeded < 0) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
}
+ if (bytesNeeded > INT_MAX - numElems + 1) {
+ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
+ }
+ bytesNeeded += numElems;
/*
* Pass 2: copy into string rep buffer.
*/
- listPtr->bytes = ckalloc((unsigned) listPtr->length);
+ listPtr->length = bytesNeeded - 1;
+ listPtr->bytes = ckalloc((unsigned) bytesNeeded);
dst = listPtr->bytes;
for (i = 0; i < numElems; i++) {
+ flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
elem = TclGetStringFromObj(elemPtrs[i], &length);
- dst += Tcl_ConvertCountedElement(elem, length, dst,
- flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH));
- *dst = ' ';
- dst++;
+ dst += TclConvertElement(elem, length, dst, flagPtr[i]);
+ *dst++ = ' ';
}
+ listPtr->bytes[listPtr->length] = '\0';
+
if (flagPtr != localFlags) {
ckfree((char *) flagPtr);
}
- if (dst == listPtr->bytes) {
- *dst = 0;
- } else {
- dst--;
- *dst = 0;
- }
- listPtr->length = dst - listPtr->bytes;
-
- /*
- * Mark the list as being canonical; although it has a string rep, it is
- * one we derived through proper "canonical" quoting and so it's known to
- * be free from nasties relating to [concat] and [eval].
- */
-
- listRepPtr->canonicalFlag = 1;
}
/*