summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--generic/tclCmdIL.c24
2 files changed, 26 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index b45d8e5..19043f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2008-09-27 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Improve the handling of the
+ case where the combination of number of elements and repeat count
+ causes the resulting list to be too large. [Bug 2130992]
+
2008-09-26 Don Porter <dgp@users.sourceforge.net>
TIP #323 IMPLEMENTATION (partial)
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 99a6cb5..73144f8 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -16,7 +16,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.153 2008/09/26 21:05:57 dgp Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.154 2008/09/27 14:16:42 dkf Exp $
*/
#include "tclInt.h"
@@ -2443,7 +2443,7 @@ Tcl_LrepeatObjCmd(
register Tcl_Obj *const objv[])
/* The argument objects. */
{
- int elementCount, i;
+ int elementCount, i, totalElems;
Tcl_Obj *listPtr, **dataArray;
List *listRepPtr;
@@ -2473,12 +2473,28 @@ Tcl_LrepeatObjCmd(
objv += 2;
/*
+ * Final sanity check. Total number of elements must fit in a signed
+ * integer. We also limit the number of elements to 512M-1 so allocations
+ * on 32-bit machines are guaranteed to be less than 2GB! [Bug 2130992]
+ */
+
+ totalElems = objc * elementCount;
+ if (totalElems/objc != elementCount || totalElems/elementCount != objc) {
+ Tcl_AppendResult(interp, "too many elements in result list", NULL);
+ return TCL_ERROR;
+ }
+ if (totalElems >= 0x20000000) {
+ Tcl_AppendResult(interp, "too many elements in result list", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
* Get an empty list object that is allocated large enough to hold each
* init value elementCount times.
*/
- listPtr = Tcl_NewListObj(elementCount*objc, NULL);
- listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
+ listPtr = Tcl_NewListObj(totalElems, NULL);
+ listRepPtr = listPtr->internalRep.twoPtrValue.ptr1;
listRepPtr->elemCount = elementCount*objc;
dataArray = &listRepPtr->elements;