-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
BufWriter is not panic-safe #30888
Copy link
Copy link
Closed
Labels
P-mediumMedium priorityMedium priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
Metadata
Metadata
Assignees
Labels
P-mediumMedium priorityMedium priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
Type
Fields
Give feedbackNo fields configured for issues without a type.
There is a panic safety issue in
BufWriter: after ainner.write()call panics, theDropimpl ofBufWritercallsinner.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: aBBBBcMore 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
unsafecode andDropimpls should have to worry about panic safety. The demo app contains none of these, so I'd consider this a bug inimpl Drop for BufWriter. (otherwise allWriteimplementations would need to provide the strong exception safety guarantee?)Solution:
BufWritercould use temporarily mark the buffer as empty during theinner.writecalls; so that theDropimpl doesn't do anything after a panic.However, this doesn't help if the panic occurs during a
bufWriter.get_mut().write()call...