summaryrefslogtreecommitdiffstats
path: root/generic/tclTest.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2020-04-22 21:28:17 (GMT)
committerdgp <dgp@users.sourceforge.net>2020-04-22 21:28:17 (GMT)
commit7f1a39781fafdf8fc0e10176a7fed4e0713a8866 (patch)
tree9ba71a03bfcfe12fcc862a42fb199d1691718dc4 /generic/tclTest.c
parent9c04c8ce98e2cb1c58d3be6d07bba35b24975443 (diff)
downloadtcl-7f1a39781fafdf8fc0e10176a7fed4e0713a8866.zip
tcl-7f1a39781fafdf8fc0e10176a7fed4e0713a8866.tar.gz
tcl-7f1a39781fafdf8fc0e10176a7fed4e0713a8866.tar.bz2
Add optional second argument to [testutfnext] that can limit how many
bytes are permitted to be read. Needed to test protection of buffer overruns.
Diffstat (limited to 'generic/tclTest.c')
-rw-r--r--generic/tclTest.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/generic/tclTest.c b/generic/tclTest.c
index 65599be..76a827a 100644
--- a/generic/tclTest.c
+++ b/generic/tclTest.c
@@ -7123,27 +7123,54 @@ TestUtfNextCmd(
int objc,
Tcl_Obj *const objv[])
{
- int numBytes;
+ int numBytes; /* Number of bytes supplied in the test string */
+ int offset; /* Number of bytes we are permitted to read */
char *bytes;
const char *result, *first;
char buffer[32];
static const char tobetested[] = "\xFF\xFE\xF4\xF2\xF0\xEF\xE8\xE3\xE2\xE1\xE0\xC2\xC1\xC0\x82";
const char *p = tobetested;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "bytes");
+ if (objc < 2 || objc > 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "bytes ?numBytes?");
return TCL_ERROR;
}
+
bytes = (char *) Tcl_GetByteArrayFromObj(objv[1], &numBytes);
+ offset = numBytes + TCL_UTF_MAX; /* If no constraint is given, allow
+ * the terminating NUL to limit
+ * operations. */
+
+ if (objc == 3) {
+ if (TCL_OK != TclGetIntForIndex(interp, objv[2], numBytes, &offset)) {
+ return TCL_ERROR;
+ }
+ if (offset < 0) {
+ offset = 0;
+ }
+ if (offset > numBytes + TCL_UTF_MAX) {
+ offset = numBytes + TCL_UTF_MAX;
+ }
+ }
+
if (numBytes > sizeof(buffer)-2) {
- Tcl_AppendResult(interp, "\"testutfnext\" can only handle 30 bytes", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"testutfnext\" can only handle %d bytes",
+ sizeof(buffer) - 2));
return TCL_ERROR;
}
memcpy(buffer + 1, bytes, numBytes);
buffer[0] = buffer[numBytes + 1] = '\x00';
+ if (!Tcl_UtfCharComplete(buffer + 1, offset)) {
+ /* Cannot scan a complete sequence from the data */
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
+ return TCL_OK;
+ }
+
first = Tcl_UtfNext(buffer + 1);
while ((buffer[0] = *p++) != '\0') {
/* Run Tcl_UtfNext with many more possible bytes at src[-1], all should give the same result */