diff options
| author | dgp <dgp@users.sourceforge.net> | 2014-06-05 15:20:59 (GMT) |
|---|---|---|
| committer | dgp <dgp@users.sourceforge.net> | 2014-06-05 15:20:59 (GMT) |
| commit | b4cc0cbac8fa4b538932247dc8ffc47748948c9d (patch) | |
| tree | ccbe4772914cfca321c5dc9f2bfff37cdf777d18 | |
| parent | 45fd54872fa0bcff3d89f8077d9a7ca220bba89f (diff) | |
| parent | 16b3c54eb00d3dea880aa5246e89df32fabec116 (diff) | |
| download | tcl-b4cc0cbac8fa4b538932247dc8ffc47748948c9d.zip tcl-b4cc0cbac8fa4b538932247dc8ffc47748948c9d.tar.gz tcl-b4cc0cbac8fa4b538932247dc8ffc47748948c9d.tar.bz2 | |
When too many chars are read by ReadChars() and we trim the limits to get it right on the next pass, don't forget the TCL_UTF_MAX padding demanded by Tcl_ExternalToUtf(). (Thanks for finding that, aku!) Fix the factorPtr management. It was just totaly wrong. The factor should be a ratio of the record of bytes read to the record of chars read. With those fixes, new test io-12.6 covers the "too many chars" code.
| -rw-r--r-- | generic/tclIO.c | 15 | ||||
| -rw-r--r-- | tests/io.test | 33 |
2 files changed, 44 insertions, 4 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 9197b06..6add83f 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -6016,10 +6016,13 @@ ReadChars( /* * We read more chars than allowed. Reset limits to - * prevent that and try again. + * prevent that and try again. Don't forget the extra + * padding of TCL_UTF_MAX - 1 bytes demanded by the + * Tcl_ExternalToUtf() call! */ - dstLimit = Tcl_UtfAtIndex(dst, charsToRead + 1) - dst; + dstLimit = Tcl_UtfAtIndex(dst, charsToRead + 1) + + TCL_UTF_MAX - 1 - dst; statePtr->flags = savedFlags; statePtr->inputEncodingFlags = savedIEFlags; statePtr->inputEncodingState = savedState; @@ -6097,8 +6100,12 @@ ReadChars( consume: bufPtr->nextRemoved += srcRead; - if (dstWrote > srcRead + 1) { - *factorPtr = dstWrote * UTF_EXPANSION_FACTOR / srcRead; + /* + * If this read contained multibyte characters, revise factorPtr + * so the next read will allocate bigger buffers. + */ + if (numChars && numChars < srcRead) { + *factorPtr = srcRead * UTF_EXPANSION_FACTOR / numChars; } Tcl_SetObjLength(objPtr, numBytes + dstWrote); return numChars; diff --git a/tests/io.test b/tests/io.test index 96ea14b..cf38a1b 100644 --- a/tests/io.test +++ b/tests/io.test @@ -1449,6 +1449,39 @@ test io-12.5 {ReadChars: fileevents on partial characters} {stdio openpipe filee lappend x [catch {close $f} msg] $msg set x } "{} timeout {} timeout \u7266 {} eof 0 {}" +test io-12.6 {ReadChars: too many chars read} { + proc driver {cmd args} { + variable buffer + variable index + set chan [lindex $args 0] + switch -- $cmd { + initialize { + set index($chan) 0 + set buffer($chan) [encoding convertto utf-8 \ + [string repeat \uBEEF 20][string repeat . 20]] + return {initialize finalize watch read} + } + finalize { + unset index($chan) buffer($chan) + return + } + watch {} + read { + set n [lindex $args 1] + set new [expr {$index($chan) + $n}] + set result [string range $buffer($chan) $index($chan) $new-1] + set index($chan) $new + return $result + } + } + } + set c [chan create read [namespace which driver]] + chan configure $c -encoding utf-8 + while {![eof $c]} { + read $c 15 + } + close $c +} {} test io-13.1 {TranslateInputEOL: cr mode} {} { set f [open $path(test1) w] |
