-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Closed
Labels
A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`Area: `std::io`, `std::fs`, `std::net` and `std::path`C-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-criticalCritical priorityCritical priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.T-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.
Description
rust/library/std/src/io/mod.rs
Lines 358 to 403 in c97f11a
| fn read_to_end_with_reservation<R, F>( | |
| r: &mut R, | |
| buf: &mut Vec<u8>, | |
| mut reservation_size: F, | |
| ) -> Result<usize> | |
| where | |
| R: Read + ?Sized, | |
| F: FnMut(&R) -> usize, | |
| { | |
| let start_len = buf.len(); | |
| let mut g = Guard { len: buf.len(), buf }; | |
| let ret; | |
| loop { | |
| if g.len == g.buf.len() { | |
| unsafe { | |
| // FIXME(danielhenrymantilla): #42788 | |
| // | |
| // - This creates a (mut) reference to a slice of | |
| // _uninitialized_ integers, which is **undefined behavior** | |
| // | |
| // - Only the standard library gets to soundly "ignore" this, | |
| // based on its privileged knowledge of unstable rustc | |
| // internals; | |
| g.buf.reserve(reservation_size(r)); | |
| let capacity = g.buf.capacity(); | |
| g.buf.set_len(capacity); | |
| r.initializer().initialize(&mut g.buf[g.len..]); | |
| } | |
| } | |
| match r.read(&mut g.buf[g.len..]) { | |
| Ok(0) => { | |
| ret = Ok(g.len - start_len); | |
| break; | |
| } | |
| Ok(n) => g.len += n, | |
| Err(ref e) if e.kind() == ErrorKind::Interrupted => {} | |
| Err(e) => { | |
| ret = Err(e); | |
| break; | |
| } | |
| } | |
| } | |
| ret | |
| } |
At line 393, the guard object's .len field is incremented by the value returned from a read implementation. If a questionable Read returns a value larger than the buffer size, it will take that value and set the length of the vector over the boundary.
This bug is reachable from Read::read_to_end() and Read::read_to_string().
Here is a playground link that demonstrates the bug. It segfaults with double free or corruption (out).
the8472, 197g, danielhenrymantilla and taiki-e
Metadata
Metadata
Assignees
Labels
A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`Area: `std::io`, `std::fs`, `std::net` and `std::path`C-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-criticalCritical priorityCritical priorityT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.T-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.