summaryrefslogtreecommitdiffstats
path: root/generic/tclUtf.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2018-10-03 19:24:13 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2018-10-03 19:24:13 (GMT)
commit50a13754610c04730f483b8100a8b9c0fccb1e3e (patch)
treeaafde258c1aa77d96056ac741540ffc2f3ad3729 /generic/tclUtf.c
parent3d5f129cb0f1208fab8b96b4a86777ea25744163 (diff)
downloadtcl-50a13754610c04730f483b8100a8b9c0fccb1e3e.zip
tcl-50a13754610c04730f483b8100a8b9c0fccb1e3e.tar.gz
tcl-50a13754610c04730f483b8100a8b9c0fccb1e3e.tar.bz2
Tcl_UniCharToUtfDString: Don't allocate too much memory for this function.
Tcl_UtfToUniCharDString: Don't allocate too much memory for this function. And make sure that we never access more than 'length' bytes from the string, not even when encountering invalid UTF-8.
Diffstat (limited to 'generic/tclUtf.c')
-rw-r--r--generic/tclUtf.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/generic/tclUtf.c b/generic/tclUtf.c
index c2963bf..b33bf5f 100644
--- a/generic/tclUtf.c
+++ b/generic/tclUtf.c
@@ -243,7 +243,7 @@ Tcl_UniCharToUtfDString(
*/
oldLength = Tcl_DStringLength(dsPtr);
- Tcl_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * TCL_UTF_MAX);
+ Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * TCL_UTF_MAX);
string = Tcl_DStringValue(dsPtr) + oldLength;
p = string;
@@ -432,17 +432,27 @@ Tcl_UtfToUniCharDString(
*/
oldLength = Tcl_DStringLength(dsPtr);
-/* TODO: fix overreach! */
+
Tcl_DStringSetLength(dsPtr,
- (int) ((oldLength + length + 1) * sizeof(Tcl_UniChar)));
+ oldLength + (int) ((length + 1) * sizeof(Tcl_UniChar)));
wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength);
w = wString;
- end = src + length;
- for (p = src; p < end; ) {
+ p = src;
+ end = src + length - TCL_UTF_MAX;
+ while (p < end) {
p += TclUtfToUniChar(p, &ch);
*w++ = ch;
}
+ end += TCL_UTF_MAX;
+ while (p < end) {
+ if (Tcl_UtfCharComplete(p, end-p)) {
+ p += TclUtfToUniChar(p, &ch);
+ } else {
+ ch = UCHAR(*p++);
+ }
+ *w++ = ch;
+ }
*w = '\0';
Tcl_DStringSetLength(dsPtr,
(oldLength + ((char *) w - (char *) wString)));