set_len grows a Vec over capacity that was never written
ID |
rust.correctness.set_len_called_uninitialized_vectors |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Undefined Behaviour |
Language |
Rust |
Description
Detects set_len(n) called on a vector immediately after Vec::with_capacity(n), with no statement in between that writes the elements. Sequences that initialise the buffer first — write_bytes, a copy_nonoverlapping through as_mut_ptr, or a safe fill — are not reported, and neither is set_len(0).
Rationale
with_capacity reserves memory without initialising it, so set_len hands out elements that were never written. Reading them is undefined behaviour for every type, and for a type with a destructor the eventual drop runs over garbage, which the optimiser is free to turn into anything at all.
The following code illustrates the pattern detected by this rule:
use std::io::Read;
pub fn read_block(len: usize, source: &mut dyn Read) -> std::io::Result<Vec<u8>> {
// FLAGGED: set_len grows a Vec over capacity that was never written
let mut buf = Vec::with_capacity(len);
unsafe { buf.set_len(len); }
source.read_exact(&mut buf)?;
Ok(buf)
}