summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2018-10-19 19:18:30 (GMT)
committerdgp <dgp@users.sourceforge.net>2018-10-19 19:18:30 (GMT)
commit50ae8fdcf6340dd85f832fb31b363e767f9430f8 (patch)
tree4a175f25784a8b477b421bf6a604039613ad19b9 /generic
parentcb061edef8250a8cd969eb0eb291f4c44d65d74e (diff)
downloadtcl-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.c46
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;
}
/*