-
Notifications
You must be signed in to change notification settings - Fork 2
Closed
Description
Hello, we have noticed a soundness issue and/or a potential security vulnerability in this crate while performing a security scan on crates.io.
Lines 160 to 165 in f1b18e1
impl<T> Index<usize> for Slab<T> { | |
type Output = T; | |
fn index(&self, index: usize) -> &Self::Output { | |
unsafe { &(*(self.mem.offset(index as isize))) } | |
} | |
} |
Lines 82 to 103 in f1b18e1
#[inline] | |
pub fn remove(&mut self, offset: usize) -> T { | |
assert!(offset < self.len, "Offset out of bounds"); | |
let elem: T; | |
let last_elem: T; | |
let elem_ptr: *mut T; | |
let last_elem_ptr: *mut T; | |
unsafe { | |
elem_ptr = self.mem.offset(offset as isize); | |
last_elem_ptr = self.mem.offset(self.len as isize); | |
elem = ptr::read(elem_ptr); | |
last_elem = ptr::read(last_elem_ptr); | |
ptr::write(elem_ptr, last_elem); | |
} | |
self.len -= 1; | |
return elem; | |
} |
Description
Slab::index()
does not perform the boundary checking, which leads to out-of-bound read access. Slab::remove()
copies an element from an invalid address due to off-by-one error, resulting in memory leakage and uninitialized memory drop.
Demonstration
- Crate: simple-slab
- Version: 0.3.2
- OS: Ubuntu 18.04.5 LTS
- Rust: rustc 1.46.0 (04488afe3 2020-08-24)
#![forbid(unsafe_code)]
mod boilerplate;
use simple_slab::Slab;
#[derive(Debug, PartialEq)]
struct DropDetector(u32);
impl Drop for DropDetector {
fn drop(&mut self) {
println!("Dropping {}", self.0);
}
}
fn main() {
boilerplate::init();
let mut slab = Slab::with_capacity(2);
slab.insert(DropDetector(123));
slab.insert(DropDetector(456));
// 1. No boundary checking leads to OOB read in `index()`
println!("{:?}", slab[20]);
// 2. Memory leak / uninitialized memory access in `remove()`
// element should be copied from `len - 1`, not `len`
assert_eq!(slab.remove(0).0, 123);
assert_eq!(slab[0].0, 456); // copied from uninitialized region `slab[2]`
}
Output:
DropDetector(3090534592)
Dropping 123
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `0`,
right: `456`', src/main.rs:49:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Dropping 0
Return Code: 101
Metadata
Metadata
Assignees
Labels
No labels