From dda585be8bc4eb50870c491eb7cd1b29eb42cef1 Mon Sep 17 00:00:00 2001 From: griffin Date: Sun, 25 Sep 2022 18:05:53 +0000 Subject: Fix out-of-bounds length bug. --- generic/tclArithSeries.c | 48 +++++++++++++++++++++++++++++++++++++----------- generic/tclArithSeries.h | 13 ++++++++----- generic/tclCmdIL.c | 26 +++++++++++++++++++------- generic/tclExecute.c | 6 +++++- generic/tclListObj.c | 2 +- tests/lseq.test | 19 +++++++++++++++++++ 6 files changed, 89 insertions(+), 25 deletions(-) diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 93177a7..3974808 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -270,8 +270,16 @@ assignNumber(int useDoubles, Tcl_WideInt *intNumberPtr, double *dblNumberPtr, Tc * None. *---------------------------------------------------------------------- */ -Tcl_Obj * -TclNewArithSeriesObj(int useDoubles, Tcl_Obj *startObj, Tcl_Obj *endObj, Tcl_Obj *stepObj, Tcl_Obj *lenObj) +int +TclNewArithSeriesObj( + Tcl_Interp *interp, /* For error reporting */ + Tcl_Obj **arithSeriesObj, /* return value */ + int useDoubles, /* Flag indicates values start, + ** end, step, are treated as doubles */ + Tcl_Obj *startObj, /* Starting value */ + Tcl_Obj *endObj, /* Ending limit */ + Tcl_Obj *stepObj, /* increment value */ + Tcl_Obj *lenObj) /* Number of elements */ { double dstart, dend, dstep; Tcl_WideInt start, end, step, len; @@ -290,7 +298,8 @@ TclNewArithSeriesObj(int useDoubles, Tcl_Obj *startObj, Tcl_Obj *endObj, Tcl_Obj dstep = step; } if (dstep == 0) { - return Tcl_NewObj(); + *arithSeriesObj = Tcl_NewObj(); + return TCL_OK; } } if (endObj) { @@ -330,11 +339,20 @@ TclNewArithSeriesObj(int useDoubles, Tcl_Obj *startObj, Tcl_Obj *endObj, Tcl_Obj } } - if (useDoubles) { - return TclNewArithSeriesDbl(dstart, dend, dstep, len); - } else { - return TclNewArithSeriesInt(start, end, step, len); + if (len > ListSizeT_MAX) { + Tcl_SetObjResult( + interp, + Tcl_NewStringObj("max length of a Tcl list exceeded", -1)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + return TCL_ERROR; } + + if (arithSeriesObj) { + *arithSeriesObj = (useDoubles) + ? TclNewArithSeriesDbl(dstart, dend, dstep, len) + : TclNewArithSeriesInt(start, end, step, len); + } + return TCL_OK; } /* @@ -684,6 +702,7 @@ TclArithSeriesObjCopy( Tcl_Obj * TclArithSeriesObjRange( + Tcl_Interp *interp, /* For error message(s) */ Tcl_Obj *arithSeriesPtr, /* List object to take a range from. */ int fromIdx, /* Index of first element to include. */ int toIdx) /* Index of last element to include. */ @@ -711,8 +730,12 @@ TclArithSeriesObjRange( if (Tcl_IsShared(arithSeriesPtr) || ((arithSeriesPtr->refCount > 1))) { - Tcl_Obj *newSlicePtr = TclNewArithSeriesObj(arithSeriesRepPtr->isDouble, - startObj, endObj, stepObj, NULL); + Tcl_Obj *newSlicePtr; + if (TclNewArithSeriesObj(interp, &newSlicePtr, + arithSeriesRepPtr->isDouble, startObj, endObj, + stepObj, NULL) != TCL_OK) { + newSlicePtr = NULL; + } Tcl_DecrRefCount(startObj); Tcl_DecrRefCount(endObj); Tcl_DecrRefCount(stepObj); @@ -875,6 +898,7 @@ TclArithSeriesGetElements( Tcl_Obj * TclArithSeriesObjReverse( + Tcl_Interp *interp, /* For error message(s) */ Tcl_Obj *arithSeriesPtr) /* List object to reverse. */ { ArithSeries *arithSeriesRepPtr; @@ -910,8 +934,10 @@ TclArithSeriesObjReverse( if (Tcl_IsShared(arithSeriesPtr) || ((arithSeriesPtr->refCount > 1))) { Tcl_Obj *lenObj = Tcl_NewWideIntObj(len); - resultObj = TclNewArithSeriesObj(isDouble, - startObj, endObj, stepObj, lenObj); + if (TclNewArithSeriesObj(interp, &resultObj, + isDouble, startObj, endObj, stepObj, lenObj) != TCL_OK) { + resultObj = NULL; + } Tcl_DecrRefCount(lenObj); } else { diff --git a/generic/tclArithSeries.h b/generic/tclArithSeries.h index f855c22..3ace052 100644 --- a/generic/tclArithSeries.h +++ b/generic/tclArithSeries.h @@ -40,9 +40,10 @@ MODULE_SCOPE int TclArithSeriesObjStep(Tcl_Obj *arithSeriesPtr, MODULE_SCOPE int TclArithSeriesObjIndex(Tcl_Obj *arithSeriesPtr, Tcl_WideInt index, Tcl_Obj **elementObj); MODULE_SCOPE Tcl_WideInt TclArithSeriesObjLength(Tcl_Obj *arithSeriesPtr); -MODULE_SCOPE Tcl_Obj * TclArithSeriesObjRange(Tcl_Obj *arithSeriesPtr, - int fromIdx, int toIdx); -MODULE_SCOPE Tcl_Obj * TclArithSeriesObjReverse(Tcl_Obj *arithSeriesPtr); +MODULE_SCOPE Tcl_Obj * TclArithSeriesObjRange(Tcl_Interp *interp, + Tcl_Obj *arithSeriesPtr, int fromIdx, int toIdx); +MODULE_SCOPE Tcl_Obj * TclArithSeriesObjReverse(Tcl_Interp *interp, + Tcl_Obj *arithSeriesPtr); MODULE_SCOPE int TclArithSeriesGetElements(Tcl_Interp *interp, Tcl_Obj *objPtr, int *objcPtr, Tcl_Obj ***objvPtr); MODULE_SCOPE Tcl_Obj * TclNewArithSeriesInt(Tcl_WideInt start, @@ -50,5 +51,7 @@ MODULE_SCOPE Tcl_Obj * TclNewArithSeriesInt(Tcl_WideInt start, Tcl_WideInt len); MODULE_SCOPE Tcl_Obj * TclNewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len); -MODULE_SCOPE Tcl_Obj * TclNewArithSeriesObj(int useDoubles, Tcl_Obj *startObj, - Tcl_Obj *endObj, Tcl_Obj *stepObj, Tcl_Obj *lenObj); +MODULE_SCOPE int TclNewArithSeriesObj(Tcl_Interp *interp, + Tcl_Obj **arithSeriesObj, int useDoubles, + Tcl_Obj *startObj, Tcl_Obj *endObj, + Tcl_Obj *stepObj, Tcl_Obj *lenObj); diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 9430eb5..f9dcc0f 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -2720,7 +2720,6 @@ Tcl_LrangeObjCmd( /* Argument objects. */ { int listLen, first, last, result; - if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "list first last"); return TCL_ERROR; @@ -2744,7 +2743,13 @@ Tcl_LrangeObjCmd( } if (TclHasInternalRep(objv[1],&tclArithSeriesType)) { - Tcl_SetObjResult(interp, TclArithSeriesObjRange(objv[1], first, last)); + Tcl_Obj *rangeObj; + rangeObj = TclArithSeriesObjRange(interp, objv[1], first, last); + if (rangeObj) { + Tcl_SetObjResult(interp, rangeObj); + } else { + return TCL_ERROR; + } } else { Tcl_SetObjResult(interp, TclListObjRange(objv[1], first, last)); } @@ -3137,8 +3142,13 @@ Tcl_LreverseObjCmd( * just to reverse it. */ if (TclHasInternalRep(objv[1],&tclArithSeriesType)) { - Tcl_SetObjResult(interp, TclArithSeriesObjReverse(objv[1])); - return TCL_OK; + Tcl_Obj *resObj = TclArithSeriesObjReverse(interp, objv[1]); + if (resObj) { + Tcl_SetObjResult(interp, resObj); + return TCL_OK; + } else { + return TCL_ERROR; + } } /* end ArithSeries */ /* True List */ @@ -4422,10 +4432,12 @@ Tcl_LseqObjCmd( /* * Success! Now lets create the series object. */ - arithSeriesPtr = TclNewArithSeriesObj(useDoubles, start, end, step, elementCount); + status = TclNewArithSeriesObj(interp, &arithSeriesPtr, + useDoubles, start, end, step, elementCount); - Tcl_SetObjResult(interp, arithSeriesPtr); - status = TCL_OK; + if (status == TCL_OK) { + Tcl_SetObjResult(interp, arithSeriesPtr); + } done: // Free number arguments. diff --git a/generic/tclExecute.c b/generic/tclExecute.c index f8d5493..5f29bfa 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5154,7 +5154,11 @@ TEBCresume( fromIdx = TclIndexDecode(fromIdx, objc - 1); if (TclHasInternalRep(valuePtr,&tclArithSeriesType)) { - objResultPtr = TclArithSeriesObjRange(valuePtr, fromIdx, toIdx); + objResultPtr = TclArithSeriesObjRange(interp, valuePtr, fromIdx, toIdx); + if (objResultPtr == NULL) { + TRACE_ERROR(interp); + goto gotError; + } } else { objResultPtr = TclListObjRange(valuePtr, fromIdx, toIdx); } diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 5034174..12b8386 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -2632,7 +2632,7 @@ TclLindexFlat( /* Handle ArithSeries as special case */ if (TclHasInternalRep(listObj,&tclArithSeriesType)) { - ListSizeT index, listLen = TclArithSeriesObjLength(listObj); + Tcl_WideInt index, listLen = TclArithSeriesObjLength(listObj); Tcl_Obj *elemObj = NULL; for (i=0 ; i Date: Mon, 26 Sep 2022 16:27:01 +0000 Subject: Fix compile error. --- generic/tclListObj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 12b8386..623689b 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -2632,7 +2632,8 @@ TclLindexFlat( /* Handle ArithSeries as special case */ if (TclHasInternalRep(listObj,&tclArithSeriesType)) { - Tcl_WideInt index, listLen = TclArithSeriesObjLength(listObj); + Tcl_WideInt listLen = TclArithSeriesObjLength(listObj); + int index; Tcl_Obj *elemObj = NULL; for (i=0 ; i Date: Wed, 28 Sep 2022 08:30:06 +0000 Subject: Still doesn't work. Use static in stead of MODULE_SCOPE --- generic/tclDecls.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 5d6e184..25adc95 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4231,7 +4231,7 @@ extern const TclStubs *tclStubsPtr; #define Tcl_GlobalEval(interp, objPtr) \ Tcl_EvalEx(interp, objPtr, TCL_INDEX_NONE, TCL_EVAL_GLOBAL) #undef Tcl_SaveResult -MODULE_SCOPE TCL_DEPRECATED_API("Use Tcl_SaveInterpState") void Tcl_SaveResult_(void) {} +static TCL_DEPRECATED_API("Use Tcl_SaveInterpState") void Tcl_SaveResult_(void) {} #define Tcl_SaveResult(interp, statePtr) \ do { \ Tcl_SaveResult_(); \ @@ -4240,7 +4240,7 @@ MODULE_SCOPE TCL_DEPRECATED_API("Use Tcl_SaveInterpState") void Tcl_SaveResult_( Tcl_SetObjResult(interp, Tcl_NewObj()); \ } while(0) #undef Tcl_RestoreResult -MODULE_SCOPE TCL_DEPRECATED_API("Use Tcl_RestoreInterpState") void Tcl_RestoreResult_(void) {} +static TCL_DEPRECATED_API("Use Tcl_RestoreInterpState") void Tcl_RestoreResult_(void) {} #define Tcl_RestoreResult(interp, statePtr) \ do { \ Tcl_RestoreResult_(); \ @@ -4249,7 +4249,7 @@ MODULE_SCOPE TCL_DEPRECATED_API("Use Tcl_RestoreInterpState") void Tcl_RestoreRe Tcl_DecrRefCount((statePtr)->objResultPtr); \ } while(0) #undef Tcl_DiscardResult -MODULE_SCOPE TCL_DEPRECATED_API("Use Tcl_DiscardInterpState") void Tcl_DiscardResult_(void) {} +static TCL_DEPRECATED_API("Use Tcl_DiscardInterpState") void Tcl_DiscardResult_(void) {} #define Tcl_DiscardResult(statePtr) \ do { \ Tcl_DiscardResult_(); \ -- cgit v0.12 From 93e50d1448aba1ed4b5eb113ea5c9b5debee85dc Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 28 Sep 2022 12:58:58 +0000 Subject: int -> ListSizeT, and a few more simplifications --- generic/tclArithSeries.c | 10 ++++++---- generic/tclListObj.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 3974808..868ce74 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -106,8 +106,10 @@ ArithSeriesLen(Tcl_WideInt start, Tcl_WideInt end, Tcl_WideInt step) { Tcl_WideInt len; - if (step == 0) return 0; - len = (step ? (1 + (((end-start))/step)) : 0); + if (step == 0) { + return 0; + } + len = 1 + ((end-start)/step); return (len < 0) ? -1 : len; } @@ -233,7 +235,7 @@ assignNumber(int useDoubles, Tcl_WideInt *intNumberPtr, double *dblNumberPtr, Tc } *number; int tcl_number_type; - if (TclGetNumberFromObj(NULL, numberObj, (ClientData*)&number, &tcl_number_type) != TCL_OK) { + if (TclGetNumberFromObj(NULL, numberObj, (void **)&number, &tcl_number_type) != TCL_OK) { return; } if (useDoubles) { @@ -818,7 +820,7 @@ TclArithSeriesGetElements( Tcl_Interp *interp, /* Used to report errors if not NULL. */ Tcl_Obj *objPtr, /* AbstractList object for which an element * array is to be returned. */ - int *objcPtr, /* Where to store the count of objects + ListSizeT *objcPtr, /* Where to store the count of objects * referenced by objv. */ Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of * pointers to the list's objects. */ diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 623689b..d18ad59 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -2633,7 +2633,7 @@ TclLindexFlat( /* Handle ArithSeries as special case */ if (TclHasInternalRep(listObj,&tclArithSeriesType)) { Tcl_WideInt listLen = TclArithSeriesObjLength(listObj); - int index; + ListSizeT index; Tcl_Obj *elemObj = NULL; for (i=0 ; i Date: Wed, 28 Sep 2022 13:57:51 +0000 Subject: Fix wrong TclGetNumberFromObj() usage: this will crash if mp_int's are involved. Everywhere else in Tcl it is used correctly --- generic/tclArithSeries.c | 18 ++++++++---------- generic/tclCmdIL.c | 7 ++----- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/generic/tclArithSeries.c b/generic/tclArithSeries.c index 868ce74..61b4a9b 100755 --- a/generic/tclArithSeries.c +++ b/generic/tclArithSeries.c @@ -229,26 +229,24 @@ TclNewArithSeriesDbl(double start, double end, double step, Tcl_WideInt len) static void assignNumber(int useDoubles, Tcl_WideInt *intNumberPtr, double *dblNumberPtr, Tcl_Obj *numberObj) { - union { - double d; - Tcl_WideInt i; - } *number; + void *clientData; int tcl_number_type; - if (TclGetNumberFromObj(NULL, numberObj, (void **)&number, &tcl_number_type) != TCL_OK) { + if (TclGetNumberFromObj(NULL, numberObj, &clientData, &tcl_number_type) != TCL_OK + || tcl_number_type == TCL_NUMBER_BIG) { return; } if (useDoubles) { - if (tcl_number_type == TCL_NUMBER_DOUBLE) { - *dblNumberPtr = number->d; + if (tcl_number_type != TCL_NUMBER_INT) { + *dblNumberPtr = *(double *)clientData; } else { - *dblNumberPtr = (double)number->i; + *dblNumberPtr = (double)*(Tcl_WideInt *)clientData; } } else { if (tcl_number_type == TCL_NUMBER_INT) { - *intNumberPtr = number->i; + *intNumberPtr = *(Tcl_WideInt *)clientData; } else { - *intNumberPtr = (Tcl_WideInt)number->d; + *intNumberPtr = (Tcl_WideInt)*(double *)clientData; } } } diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 5821a35..62ceeea 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -4077,12 +4077,9 @@ SequenceIdentifyArgument( int status; SequenceOperators opmode; SequenceByMode bymode; - union { - Tcl_WideInt i; - double d; - } nvalue; + void *clientData; - status = TclGetNumberFromObj(NULL, argPtr, (ClientData*)&nvalue, keywordIndexPtr); + status = TclGetNumberFromObj(NULL, argPtr, &clientData, keywordIndexPtr); if (status == TCL_OK) { if (numValuePtr) { *numValuePtr = argPtr; -- cgit v0.12