diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2018-12-13 20:01:34 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2018-12-13 20:01:34 (GMT) |
commit | 9c5dc4c207e6610aa3d55e2d4d081779848a21c6 (patch) | |
tree | fc9cd49a7e54859c46ce5c62037c410d47c2211a /generic/tclStringObj.c | |
parent | 1961633531b70d5a6e627f86153f4d15e722ea8b (diff) | |
download | tcl-9c5dc4c207e6610aa3d55e2d4d081779848a21c6.zip tcl-9c5dc4c207e6610aa3d55e2d4d081779848a21c6.tar.gz tcl-9c5dc4c207e6610aa3d55e2d4d081779848a21c6.tar.bz2 |
Fix 2 TIP #502 corner-cases. Those corner-cases where (probably) always wrong on 32-bit systems, but now we have a TIP describing how it's expected to behave!
Thanks to Emiliano for noticing and reporting it. Added 6 test-cases for completeness, 2 of them failed before this fix.
Also optimize TclStringLast() a bit, implementing the pre-condition tests as in TclStringFirst().
Diffstat (limited to 'generic/tclStringObj.c')
-rw-r--r-- | generic/tclStringObj.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 4e6cdc5..72ca7cd 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3568,6 +3568,10 @@ TclStringFirst( /* Find bytes in bytes */ bh = Tcl_GetByteArrayFromObj(haystack, &lh); + if ((lh < ln) || (start > lh - ln)) { + /* Don't start the loop if there cannot be a valid answer */ + return -1; + } end = bh + lh; try = bh + start; @@ -3610,6 +3614,10 @@ TclStringFirst( Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln); uh = Tcl_GetUnicodeFromObj(haystack, &lh); + if ((lh < ln) || (start > lh - ln)) { + /* Don't start the loop if there cannot be a valid answer */ + return -1; + } end = uh + lh; for (try = uh + start; try + ln <= end; try++) { @@ -3658,20 +3666,19 @@ TclStringLast( return -1; } - lh = Tcl_GetCharLength(haystack); - if (last >= lh) { - last = lh - 1; - } - - if (last < ln - 1) { - return -1; - } - if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) { unsigned char *try, *bh = Tcl_GetByteArrayFromObj(haystack, &lh); unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); + if (last >= lh) { + last = lh - 1; + } + if (last + 1 < ln) { + /* Don't start the loop if there cannot be a valid answer */ + return -1; + } try = bh + last + 1 - ln; + while (try >= bh) { if ((*try == bn[0]) && (0 == memcmp(try+1, bn+1, ln-1))) { @@ -3686,6 +3693,13 @@ TclStringLast( Tcl_UniChar *try, *uh = Tcl_GetUnicodeFromObj(haystack, &lh); Tcl_UniChar *un = Tcl_GetUnicodeFromObj(needle, &ln); + if (last >= lh) { + last = lh - 1; + } + if (last + 1 < ln) { + /* Don't start the loop if there cannot be a valid answer */ + return -1; + } try = uh + last + 1 - ln; while (try >= uh) { if ((*try == un[0]) |