3 ms·
This error is possible in Rust, but not easy to cause. Uninitialised memory is considered unsafe. There aren't any loopholes even for "just bytes". You can't
by pornel 4y ago
This error is possible in Rust, but not easy to cause.
Uninitialised memory is considered unsafe. There aren't any loopholes even for "just bytes". You can't accidentally make an uninitialised buffer, and you can't expose one without explicit `unsafe{}`.
Sych unsafe code is typically wrapped in safe interfaces, so the risk is limited to implementation side, and not spread to every usage site.
For filling buffers the language pushes towards use of growable Vec with capacity that tracks how much has been initialised, or to collect straight from an iterator, which is foolproof.
Custom buffers are not even used that often, because things like zip writing or compression use io::Write streaming interface.
- notriddle 4y agoIt's actually not very hard to cause. It would happen if your system reuses buffers without actually going through the allocator. Something like this: let mut buf = vec![0; DEFAULT_BUFFER_SIZE]; let database_frame_len = database_socket.read(&mut buf)?; // use 1 let database_result = Database::parse(&buf[..database_frame_len])?; let html_template = HtmlTemplate::new(database_result); let html_len = html_template.write(&mut buf)?; // use 2 socket.write(&buf[..html_len]); The above code makes the tenuous assumption that HtmlTemplate::write actually clobbers everything it's supposed to write. But it doesn't even require unsafe code for it to not do that, because the underlying buffer is entirely initialized according to the type system. The only advice I can really give to avoid this kind of bug is: don't reuse buffers unless it's actually a bottleneck.
- pcwalton 4y agoCouldn't you fix that by just clearing the buffer in between the two calls? It won't be measurably slower to do that because the buffer should retain its allocated capacity.
- notriddle 4y agoIt's not a difficult bug to fix, but it is a very difficult bug to detect, since miri won't think anything is wrong.
- pornel 4y agoThis is why I've mentioned io::Write, because people don't chop buffers like that with C-style separately tracked length when they can have zero-copy: html_template.pipe_to(socket); and there's a foolproof io::BufWriter adapter if you need these writes buffered.