P.UNS.SAS.03 不要随便在公开的 API 中暴露未初始化内存
【描述】
在公开的API中暴露未初始化内存可能导致 未定义行为。 关于未定义行为,可以参考Unsafe 代码术语指南。
【反例】
#![allow(unused)] fn main() { // 以下是有安全风险的代码示例: impl<R> BufRead for GreedyAccessReader<R> where R: Read, { fn fill_buf(&mut self) -> IoResult<&[u8]> { if self.buf.capacity() == self.consumed { self.reserve_up_to(self.buf.capacity() + 16); } let b = self.buf.len(); let buf = unsafe { // safe because it's within the buffer's limits // and we won't be reading uninitialized memory // 这里虽然没有读取未初始化内存,但是会导致用户读取 std::slice::from_raw_parts_mut( self.buf.as_mut_ptr().offset(b as isize), self.buf.capacity() - b) }; match self.inner.read(buf) { Ok(o) => { unsafe { // reset the size to include the written portion, // safe because the extra data is initialized self.buf.set_len(b + o); } Ok(&self.buf[self.consumed..]) } Err(e) => Err(e), } } fn consume(&mut self, amt: usize) { self.consumed += amt; } } // 另外一个漏洞代码 fn read_vec(&mut self) -> Result<Vec<u8>> { let len: u32 = de::Deserialize::deserialize(&mut *self)?; // 创建了未初始化buf let mut buf = Vec::with_capacity(len as usize); unsafe { buf.set_len(len as usize) } self.read_size(u64::from(len))?; // 将其传递给了用户提供的`Read`实现 self.reader.read_exact(&mut buf[..])?; Ok(buf) } }
【正例】
#![allow(unused)] fn main() { // 修正以后的代码示例,去掉了未初始化的buf: impl<R> BufRead for GreedyAccessReader<R> where R: Read, { fn fill_buf(&mut self) -> IoResult<&[u8]> { if self.buf.capacity() == self.consumed { self.reserve_up_to(self.buf.capacity() + 16); } let b = self.buf.len(); self.buf.resize(self.buf.capacity(), 0); let buf = &mut self.buf[b..]; let o = self.inner.read(buf)?; // truncate to exclude non-written portion self.buf.truncate(b + o); Ok(&self.buf[self.consumed..]) } fn consume(&mut self, amt: usize) { self.consumed += amt; } } // 另外一个已修正漏洞的代码 fn read_vec(&mut self) -> Result<Vec<u8>> { let len: u32 = de::Deserialize::deserialize(&mut *self)?; // 创建了未初始化buf let mut buf = Vec::with_capacity(len as usize); // 初始化为 0; buf.resize(len as usize, 0); self.read_size(u64::from(len))?; // 将其传递给了用户提供的`Read`实现 self.reader.read_exact(&mut buf[..])?; Ok(buf) } }