Description
There is a panic safety issue in BufWriter
: after a inner.write()
call panics, the Drop
impl of BufWriter
calls inner.write()
again, which means the buffer contents are potentially written twice. This may cause an application to overwrite parts of a file that it did not mean to overwrite (in a DB engine written in Rust, this could cause unrecoverable data corruption!).
Demonstration: https://play.rust-lang.org/?gist=9991550d3efb38c93df4&version=stable
The expected output of the demo program is File contents: aBBccc
, the actual output is: File contents: aBBBBc
More generally, we need a story for panic safety in Rust.
My takeaway from the related discussions (e.g. RFC 1236, #27719, the RecoverSafe trait) was that only unsafe
code and Drop
impls should have to worry about panic safety. The demo app contains none of these, so I'd consider this a bug in impl Drop for BufWriter
. (otherwise all Write
implementations would need to provide the strong exception safety guarantee?)
Solution: BufWriter
could use temporarily mark the buffer as empty during the inner.write
calls; so that the Drop
impl doesn't do anything after a panic.
However, this doesn't help if the panic occurs during a bufWriter.get_mut().write()
call...