summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2023-04-15 11:54:27 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2023-04-15 11:54:27 (GMT)
commitafacee3f07729501638d6afc6f21bee9c01ef7f2 (patch)
tree720b2085f3c1c9bf0745a3b03607ea2ff8bde3f1
parentb52ee10fc782b1628003c6068b593ae2cb69d0e7 (diff)
downloadtcl-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.c9
-rw-r--r--tests/io.test26
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}}
# ### ### ### ######### ######### #########