diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2017-06-08 12:34:08 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2017-06-08 12:34:08 (GMT) |
commit | 8cb64e1074f47fa62a4f2461569272a27a57f9d6 (patch) | |
tree | 7cb6ffd5997ad4029500329d6fbe490d5c5afff3 /generic | |
parent | 829350cc1a1b9d065ccda17583ee55c731598f13 (diff) | |
download | tcl-8cb64e1074f47fa62a4f2461569272a27a57f9d6.zip tcl-8cb64e1074f47fa62a4f2461569272a27a57f9d6.tar.gz tcl-8cb64e1074f47fa62a4f2461569272a27a57f9d6.tar.bz2 |
Fix [2738427]: Tcl_NumUtfChars(...) no overflow check.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclUtf.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 3937141..a405367 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -464,7 +464,6 @@ Tcl_NumUtfChars( * for strlen(string). */ { Tcl_UniChar ch; - register Tcl_UniChar *chPtr = &ch; register int i; /* @@ -477,23 +476,25 @@ Tcl_NumUtfChars( i = 0; if (length < 0) { while (*src != '\0') { - src += TclUtfToUniChar(src, chPtr); + src += TclUtfToUniChar(src, &ch); i++; } + if (i < 0) i = INT_MAX; /* Bug [2738427] */ } else { - register int n; - - while (length > 0) { - if (UCHAR(*src) < 0xC0) { - length--; - src++; - } else { - n = Tcl_UtfToUniChar(src, chPtr); - length -= n; - src += n; - } + register const char *endPtr = src + length - TCL_UTF_MAX; + + while (src < endPtr) { + src += TclUtfToUniChar(src, &ch); i++; } + endPtr += TCL_UTF_MAX; + while ((src < endPtr) && Tcl_UtfCharComplete(src, endPtr - src)) { + src += TclUtfToUniChar(src, &ch); + i++; + } + if (src < endPtr) { + i += endPtr - src; + } } return i; } |