-
Notifications
You must be signed in to change notification settings - Fork 13.6k
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.