Closed JOE1994 closed 3 years ago
Hi, @JOE1994.
Record::read method creates an uninitialized buffer and passes it to user-provided Read implementation. This is unsound, because it allows safe Rust code to exhibit an undefined behavior (read from uninitialized memory).
This is definitely an issue. Thanks!
Another question I have regarding Record::read(): Right before data.set_len(len), why data.reserve(len - 5) instead of data.reserve(len)?
Total length of a record is len
and 5 bytes of capacity we already have, therefore we need to reserve space for len - 5
additional bytes (see std::vec::Vec::reserve
).
Hello :crab:, we (Rust group @sslab-gatech) found a memory-safety/soundness issue in this crate while scanning Rust code on crates.io for potential vulnerabilities.
Issue Description
https://github.com/blackbeam/rust-marc/blob/e94b984c975a7aad327592c83a88a043a8709f23/src/lib.rs#L122-L129
Record::read
method creates an uninitialized buffer and passes it to user-providedRead
implementation. This is unsound, because it allows safe Rust code to exhibit an undefined behavior (read from uninitialized memory).This part from the
Read
trait documentation explains the issue:Another question I have regarding
Record::read()
: Right beforedata.set_len(len)
, whydata.reserve(len - 5)
instead ofdata.reserve(len)
? At the momment it seems unsound to me :(How to fix the issue?
The Naive & safe way to fix the issue is to always zero-initialize a buffer before lending it to a user-provided
Read
implementation. Note that this approach will add runtime performance overhead of zero-initializing the buffer.As of Jan 2021, there is not yet an ideal fix that works in stable Rust with no performance overhead. Below are links to relevant discussions & suggestions for the fix.
std::io::Initializer