Skip to content

Commit

Permalink
Proposed fix for [154ed7ce56]: Tcl 9: [gets] on -strictencoding 1 con…
Browse files Browse the repository at this point in the history
…figured channel.

Extracted from TIP #657 branch (better keeping bug-fix separate from enhancements)
  • Loading branch information
jan.nijtmans committed Mar 20, 2023
1 parent 68b7063 commit 45e6151
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
26 changes: 19 additions & 7 deletions generic/tclIO.c
Original file line number Diff line number Diff line change
Expand Up @@ -4914,6 +4914,19 @@ Tcl_GetsObj(
goto done;
}
goto gotEOL;
} else if (gs.bytesWrote == 0
&& GotFlag(statePtr, CHANNEL_ENCODING_ERROR)
&& !GotFlag(statePtr, CHANNEL_NONBLOCKING)) {
/* Set eol to the position that caused the encoding error, and then
* coninue to gotEOL, which stores the data that was decoded
* without error to objPtr. This allows the caller to do something
* useful with the data decoded so far, and also results in the
* position of the file being the first byte that was not
* succesfully decoded, allowing further processing at exactly that
* point, if desired.
*/
eol = dstEnd;
goto gotEOL;
}
dst = dstEnd;
}
Expand Down Expand Up @@ -5030,6 +5043,11 @@ Tcl_GetsObj(
}
UpdateInterest(chanPtr);
TclChannelRelease((Tcl_Channel)chanPtr);
if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR) &&
(copiedTotal == 0 || !GotFlag(statePtr, CHANNEL_NONBLOCKING))) {
Tcl_SetErrno(EILSEQ);
copiedTotal = -1;
}
return copiedTotal;
}

Expand Down Expand Up @@ -7534,8 +7552,7 @@ Tcl_Eof(
ChannelState *statePtr = ((Channel *) chan)->state;
/* State of real channel structure. */

if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_FCOPY)
&& GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
return 0;
}
return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0;
Expand Down Expand Up @@ -9751,7 +9768,6 @@ CopyData(
* the bottom of the stack.
*/

SetFlag(inStatePtr, CHANNEL_FCOPY);
inBinary = (inStatePtr->encoding == NULL);
outBinary = (outStatePtr->encoding == NULL);
sameEncoding = inStatePtr->encoding == outStatePtr->encoding
Expand Down Expand Up @@ -9867,7 +9883,6 @@ CopyData(
TclDecrRefCount(bufObj);
bufObj = NULL;
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return TCL_OK;
}
}
Expand Down Expand Up @@ -9959,7 +9974,6 @@ CopyData(
TclDecrRefCount(bufObj);
bufObj = NULL;
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return TCL_OK;
}

Expand All @@ -9982,7 +9996,6 @@ CopyData(
TclDecrRefCount(bufObj);
bufObj = NULL;
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return TCL_OK;
}
} /* while */
Expand Down Expand Up @@ -10035,7 +10048,6 @@ CopyData(
}
}
}
ResetFlag(inStatePtr, CHANNEL_FCOPY);
return result;
}

Expand Down
2 changes: 0 additions & 2 deletions generic/tclIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,6 @@ typedef struct ChannelState {
* flushed after every newline. */
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
* be flushed immediately. */
#define CHANNEL_FCOPY (1<<6) /* Channel is currently doing an fcopy
* mode. */
#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued
* output buffers has been
* scheduled. */
Expand Down
20 changes: 18 additions & 2 deletions tests/io.test
Original file line number Diff line number Diff line change
Expand Up @@ -9155,6 +9155,22 @@ test io-75.5 {invalid utf-8 encoding read is ignored (-profile tcl8)} -setup {
removeFile io-75.5
} -result 4181

test io-75.6 {invalid utf-8 encoding gets is not ignored (-profile strict)} -setup {
set fn [makeFile {} io-75.6]
set f [open $fn w+]
fconfigure $f -encoding binary
# \x81 is invalid 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 {
gets $f
} -cleanup {
close $f
removeFile io-75.6
} -match glob -returnCodes 1 -result {error reading "*": illegal byte sequence}

test io-75.8 {invalid utf-8 encoding eof handling (-profile strict)} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
Expand Down Expand Up @@ -9243,10 +9259,10 @@ test io-75.12 {invalid utf-8 encoding read is ignored} -setup {
fconfigure $f -encoding utf-8 -buffering none -eofchar "" -translation lf
} -body {
set d [read $f]
close $f
binary scan $d H* hd
set hd
} -cleanup {
close $f
removeFile io-75.12
} -result 4181
test io-75.13 {invalid utf-8 encoding read is not ignored (-profile strict)} -setup {
Expand All @@ -9262,9 +9278,9 @@ test io-75.13 {invalid utf-8 encoding read is not ignored (-profile strict)} -se
set d [read $f]
binary scan $d H* hd
lappend hd [catch {read $f} msg]
close $f
lappend hd $msg
} -cleanup {
close $f
removeFile io-75.13
} -match glob -result {41 1 {error reading "*": illegal byte sequence}}

Expand Down

0 comments on commit 45e6151

Please sign in to comment.