From e5a2ebd71b2aa2b31ca5128eb47ae0a7fdd20bd5 Mon Sep 17 00:00:00 2001
From: "jan.nijtmans" <nijtmans@users.sourceforge.net>
Date: Mon, 17 Jan 2022 10:35:18 +0000
Subject: Follow-up to [767e070d35]: Tcl_GetRange and Tcl_GetUniChar do not
 validate index inputs. Now that Tcl_GetRange() checks its arguments, the
 callers of this function don't have to do that any more. This also shows a
 off-by-one error in the Tcl_GetRange() check

---
 generic/tclCmdMZ.c     | 10 +---------
 generic/tclExecute.c   | 33 ++++-----------------------------
 generic/tclStringObj.c |  7 +++----
 3 files changed, 8 insertions(+), 42 deletions(-)

diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index da3fc8b..5422b7f 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -2183,15 +2183,7 @@ StringRangeCmd(
 	return TCL_ERROR;
     }
 
-    if (first < 0) {
-	first = 0;
-    }
-    if (last >= length) {
-	last = length;
-    }
-    if (last >= first) {
-	Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last));
-    }
+    Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last));
     return TCL_OK;
 }
 
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index e5a6b71..c39bc21 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -5609,17 +5609,7 @@ TEBCresume(
 	    goto gotError;
 	}
 
-	if (fromIdx < 0) {
-	    fromIdx = 0;
-	}
-	if (toIdx >= length) {
-	    toIdx = length;
-	}
-	if (toIdx >= fromIdx) {
-	    objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx);
-	} else {
-	    TclNewObj(objResultPtr);
-	}
+	objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx);
 	TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr)));
 	NEXT_INST_V(1, 3, 1);
 
@@ -5652,13 +5642,6 @@ TEBCresume(
 	}
 
 	toIdx = TclIndexDecode(toIdx, length - 1);
-	if (toIdx < 0) {
-	    goto emptyRange;
-	} else if (toIdx >= length) {
-	    toIdx = length - 1;
-	}
-
-	assert ( toIdx >= 0 && toIdx < length );
 
 	/*
 	assert ( fromIdx != TCL_INDEX_BEFORE );
@@ -5670,19 +5653,11 @@ TEBCresume(
 	    fromIdx = TCL_INDEX_START;
 	}
 	if (fromIdx == TCL_INDEX_AFTER) {
-	    goto emptyRange;
-	}
-
-	fromIdx = TclIndexDecode(fromIdx, length - 1);
-	if (fromIdx < 0) {
-	    fromIdx = 0;
-	}
-
-	if (fromIdx <= toIdx) {
-	    objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
-	} else {
 	emptyRange:
 	    TclNewObj(objResultPtr);
+	} else {
+	    fromIdx = TclIndexDecode(fromIdx, length - 1);
+	    objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
 	}
 	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
 	NEXT_INST_F(9, 1, 1);
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index edfcb9f..fc675cf 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -739,8 +739,7 @@ Tcl_GetUnicodeFromObj(
  *
  *	Create a Tcl Object that contains the chars between first and last of
  *	the object indicated by "objPtr". If the object is not already a
- *	String object, convert it to one. The first and last indices are
- *	assumed to be in the appropriate range.
+ *	String object, convert it to one.
  *
  * Results:
  *	Returns a new Tcl Object of the String type.
@@ -818,8 +817,8 @@ Tcl_GetRange(
 	FillUnicodeRep(objPtr);
 	stringPtr = GET_STRING(objPtr);
     }
-    if (last > stringPtr->numChars) {
-	last = stringPtr->numChars;
+    if (last >= stringPtr->numChars) {
+	last = stringPtr->numChars - 1;
     }
     if (last < first) {
 	return Tcl_NewObj();
-- 
cgit v0.12