4 ms·
It'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
by notriddle 4y ago
It'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.