summaryrefslogtreecommitdiffstats
path: root/generic/tclUtf.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2017-06-08 12:34:08 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2017-06-08 12:34:08 (GMT)
commit8cb64e1074f47fa62a4f2461569272a27a57f9d6 (patch)
tree7cb6ffd5997ad4029500329d6fbe490d5c5afff3 /generic/tclUtf.c
parent829350cc1a1b9d065ccda17583ee55c731598f13 (diff)
downloadtcl-8cb64e1074f47fa62a4f2461569272a27a57f9d6.zip
tcl-8cb64e1074f47fa62a4f2461569272a27a57f9d6.tar.gz
tcl-8cb64e1074f47fa62a4f2461569272a27a57f9d6.tar.bz2
Fix [2738427]: Tcl_NumUtfChars(...) no overflow check.
Diffstat (limited to 'generic/tclUtf.c')
-rw-r--r--generic/tclUtf.c27
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;
}