diff options
author | dgp <dgp@users.sourceforge.net> | 2018-10-19 19:18:30 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2018-10-19 19:18:30 (GMT) |
commit | 50ae8fdcf6340dd85f832fb31b363e767f9430f8 (patch) | |
tree | 4a175f25784a8b477b421bf6a604039613ad19b9 /generic | |
parent | cb061edef8250a8cd969eb0eb291f4c44d65d74e (diff) | |
download | tcl-50ae8fdcf6340dd85f832fb31b363e767f9430f8.zip tcl-50ae8fdcf6340dd85f832fb31b363e767f9430f8.tar.gz tcl-50ae8fdcf6340dd85f832fb31b363e767f9430f8.tar.bz2 |
[d1d05d1c7a] Tests and fix for bignums in end-offset index value parsing.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclUtil.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 4ea9c2e..d3136e2 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3660,10 +3660,12 @@ TclFormatInt( * GetWideForIndex -- * * This function produces a wide integer value corresponding to the - * list index held in *objPtr. The parsing supports all values + * index value held in *objPtr. The parsing supports all values * recognized as any size of integer, and the syntaxes end[-+]$integer * and $integer[-+]$integer. The argument endValue is used to give - * the meaning of the literal index value "end". + * the meaning of the literal index value "end". Index arithmetic + * on arguments outside the wide integer range are only accepted + * when interp is a working interpreter, not NULL. * * Results: * When parsing of *objPtr successfully recognizes an index value, @@ -3994,6 +3996,8 @@ SetEndOffsetFromAny( bytes = TclGetStringFromObj(objPtr, &length); if ((*bytes != 'e') || (strncmp(bytes, "end", (size_t)((length > 3) ? 3 : length)) != 0)) { + + badIndexFormat: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\": must be end?[+-]integer?", bytes)); @@ -4013,35 +4017,33 @@ SetEndOffsetFromAny( * This is our limited string expression evaluator. Pass everything * after "end-" to TclParseNumber. */ + ClientData cd; + int t; if (TclIsSpaceProc(bytes[4])) { goto badIndexFormat; } if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, TCL_PARSE_INTEGER_ONLY) != TCL_OK) { - return TCL_ERROR; - } - if (objPtr->typePtr != &tclIntType) { - goto badIndexFormat; + goto badIndexFormat; } - offset = objPtr->internalRep.wideValue; - if (bytes[3] == '-') { - - /* TODO: Review overflow concerns here! */ - offset = -offset; + TclGetNumberFromObj(NULL, objPtr, &cd, &t); + if (t == TCL_NUMBER_BIG) { + /* Truncate to the signed wide range. */ + if (mp_isneg((mp_int *)cd)) { + offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; + } else { + offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; + } + } else { + /* assert (t == TCL_NUMBER_INT); */ + offset = (*(Tcl_WideInt *)cd); + if (bytes[3] == '-') { + offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; + } } } else { - /* - * Conversion failed. Report the error. - */ - - badIndexFormat: - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad index \"%s\": must be end?[+-]integer?", bytes)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); - } - return TCL_ERROR; + goto badIndexFormat; } /* |