Description
LineWriter
can return an error after a partial write if flushing the inner BufWriter
fails (
rust/src/libstd/io/buffered.rs
Line 766 in cb343c3
Ok(bytes_written)
, ignoring the error.
OLD REPORT:
I originally thought this problem was systematic so I audited stdlib. Apparently it isn't... See below.
The write trait guarantees:
If an error is returned then no bytes in the buffer were written to this writer.
However, this is violated all over stdlib. For example, if "abc\nde"
is written to a LineWriter
, the LineWriter
could write "abc"
, try to flush, and then return an error due to a failed flush. However, "abc"
has been written violating the spec.
IMO, the solution is to return Ok(amount_written)
for partial writes and drop the error (if any). This should be safe because of write's write-xor-error guarantee. If the error was transient, the caller never needs to know. Otherwise, they will will learn of it on the next write.
Here's everything in the stdlib that implements write (and should be audited):
-
Sink
inlibrustdoc/test.rs
-
Sink
inlibstd/io/util.rs
-
&'a mut W
inlibstd/io/impls.rs
-
Box<W>
inlibstd/io/impls.rs
-
&'a mut [u8]
inlibstd/io/impls.rs
-
Vec<u8>
inlibstd/io/impls.rs
-
Cursor<&'a mut [u8]>
inlibstd/io/cursor.rs
-
Cursor<Vec<u8>>
inlibstd/io/cursor.rs
-
Cursor<Box<[u8]>>
inlibstd/io/cursor.rs
-
StdoutRaw
inlibstd/io/stdio.rs
-
StderrRaw
inlibstd/io/stdio.rs
-
Maybe<W>
inlibstd/io/stdio.rs
-
Stdout
inlibstd/io/stdio.rs
-
StdoutLock<'a>
inlibstd/io/stdio.rs
-
Stderr
inlibstd/io/stdio.rs
-
StderrLock<'a>
inlibstd/io/stdio.rs
-
BufWriter<W>
inlibstd/io/buffered.rs
-
LineWriter<W>
inlibstd/io/buffered.rs
(buggy) -
Broadcast<T, U>
inlibstd/io/mod.rs
(buggy but unfixable and deprecated). -
TcpStream
inlibstd/net/tcp.rs
-
&'a TcpStream
inlibstd/net/tcp.rs
-
Stderr
inlibstd/sys/unix/stdio.rs
-
Stderr
inlibstd/sys/windows/stdio.rs
(panics on partial write) -
ChildStdin
inlibstd/process.rs
-
File
inlibstd/fs.rs
-
&'a File
inlibstd/fs.rs