diff options
author | dgp <dgp@users.sourceforge.net> | 2020-04-22 21:28:17 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2020-04-22 21:28:17 (GMT) |
commit | 7f1a39781fafdf8fc0e10176a7fed4e0713a8866 (patch) | |
tree | 9ba71a03bfcfe12fcc862a42fb199d1691718dc4 /generic/tclTest.c | |
parent | 9c04c8ce98e2cb1c58d3be6d07bba35b24975443 (diff) | |
download | tcl-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.c | 35 |
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 */ |