diff options
author | pooryorick <com.digitalsmarties@pooryorick.com> | 2023-04-15 11:54:27 (GMT) |
---|---|---|
committer | pooryorick <com.digitalsmarties@pooryorick.com> | 2023-04-15 11:54:27 (GMT) |
commit | afacee3f07729501638d6afc6f21bee9c01ef7f2 (patch) | |
tree | 720b2085f3c1c9bf0745a3b03607ea2ff8bde3f1 | |
parent | b52ee10fc782b1628003c6068b593ae2cb69d0e7 (diff) | |
download | tcl-afacee3f07729501638d6afc6f21bee9c01ef7f2.zip tcl-afacee3f07729501638d6afc6f21bee9c01ef7f2.tar.gz tcl-afacee3f07729501638d6afc6f21bee9c01ef7f2.tar.bz2 |
Fix for [a7a89d422a4f5dd3], Under strict encoding, [gets] returns an error instead of returning the second line.
Also, ensure that position in file does not change if [gets] return an error.
-rw-r--r-- | generic/tclIO.c | 9 | ||||
-rw-r--r-- | tests/io.test | 26 |
2 files changed, 20 insertions, 15 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index aa82f89..3fd8d48 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -4616,6 +4616,7 @@ Tcl_GetsObj( if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) { UpdateInterest(chanPtr); + ResetFlag(statePtr, CHANNEL_ENCODING_ERROR); Tcl_SetErrno(EILSEQ); return TCL_INDEX_NONE; } @@ -4632,7 +4633,7 @@ Tcl_GetsObj( if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { SetFlag(statePtr, CHANNEL_EOF); assert(statePtr->inputEncodingFlags & TCL_ENCODING_END); - assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR)); +assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR)); /* TODO: Do we need this? */ UpdateInterest(chanPtr); @@ -4998,9 +4999,11 @@ Tcl_GetsObj( UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR) && gs.bytesWrote == 0) { + bufPtr->nextRemoved = oldRemoved; Tcl_SetErrno(EILSEQ); copiedTotal = -1; } + ResetFlag(statePtr, CHANNEL_ENCODING_ERROR); return copiedTotal; } @@ -5462,6 +5465,8 @@ FilterInputBytes( if (result == TCL_CONVERT_UNKNOWN || result == TCL_CONVERT_SYNTAX) { SetFlag(statePtr, CHANNEL_ENCODING_ERROR); + ResetFlag(statePtr, CHANNEL_STICKY_EOF); + ResetFlag(statePtr, CHANNEL_EOF); result = TCL_OK; } @@ -7589,7 +7594,7 @@ Tcl_InputBuffered( } /* - * Don't forget the bytes in the topmost pushback area. + * Remember the bytes in the topmost pushback area. */ for (bufPtr = statePtr->topChanPtr->inQueueHead; bufPtr != NULL; diff --git a/tests/io.test b/tests/io.test index 286a136..7a35e0e 100644 --- a/tests/io.test +++ b/tests/io.test @@ -9266,13 +9266,14 @@ test io-75.6 {invalid utf-8 encoding, gets is not ignored (-profile strict)} -se set fn [makeFile {} io-75.6] set f [open $fn w+] fconfigure $f -encoding binary - # \x81 is invalid in utf-8 + # \x81 is an incomplete byte sequence in utf-8 puts -nonewline $f A\x81 flush $f seek $f 0 fconfigure $f -encoding utf-8 -buffering none -eofchar {} \ -translation lf -profile strict } -body { +after 1 gets $f } -cleanup { close $f @@ -9452,13 +9453,14 @@ test io-75.14 { set chan [file tempfile] fconfigure $f -encoding binary # \xc0\n is an invalid utf-8 sequence - puts -nonewline $f a\nb\xc0\nc\n + puts -nonewline $f a\nb\nc\xc0\nd\n flush $f seek $f 0 fconfigure $f -encoding utf-8 -buffering none -eofchar {} \ -translation lf -profile strict } -body { lappend res [gets $f] + lappend res [gets $f] set status [catch {gets $f} cres copts] lappend res $status $cres chan configure $f -profile tcl8 @@ -9466,36 +9468,34 @@ test io-75.14 { lappend res [gets $f] close $f return $res -} -match glob -result {a 1 {error reading "*":\ - invalid or incomplete multibyte or wide character} bÀ c} +} -match glob -result {a b 1 {error reading "*":\ + invalid or incomplete multibyte or wide character} cÀ d} test io-75.15 { - invalid utf-8 encoding strict gets does not hang - after error reconfigure and read + invalid utf-8 encoding strict + gets does not hang + gets succeeds for the first two lines } -setup { set res {} set chan [file tempfile] fconfigure $chan -encoding binary # \xc0\x40 is an invalid utf-8 sequence - puts $chan hello\nAB\xc0\x40CD\nEFG + puts $chan hello\nAB\nCD\xc0\x40EF\nGHI seek $chan 0 } -body { #Now try to read it with [gets] fconfigure $chan -encoding utf-8 -profile strict lappend res [gets $chan] + lappend res [gets $chan] set status [catch {gets $chan} cres copts] lappend res $status $cres set status [catch {gets $chan} cres copts] lappend res $status $cres - chan configure $chan -encoding binary - foreach char [split [read $chan 6] {}] { - lappend res [format %x [scan $char %c]] - } return $res } -cleanup { close $chan -} -match glob -result {hello 1 {error reading "*": invalid or incomplete multibyte or wide character}\ - 1 {error reading "*": invalid or incomplete multibyte or wide character} 41 42 c0 40 43 44} +} -match glob -result {hello AB 1 {error reading "*": invalid or incomplete multibyte or wide character}\ + 1 {error reading "*": invalid or incomplete multibyte or wide character}} # ### ### ### ######### ######### ######### |