Don’t hold onto ReadOptions.inner when iterating (#655)

master
Michal Nazarewicz 2 years ago committed by GitHub
parent 908049d9e7
commit 947e4b6303
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/db_iterator.rs
  2. 4
      src/db_options.rs

@ -72,10 +72,10 @@ pub type DBRawIterator<'a> = DBRawIteratorWithThreadMode<'a, DB>;
pub struct DBRawIteratorWithThreadMode<'a, D: DBAccess> { pub struct DBRawIteratorWithThreadMode<'a, D: DBAccess> {
inner: std::ptr::NonNull<ffi::rocksdb_iterator_t>, inner: std::ptr::NonNull<ffi::rocksdb_iterator_t>,
/// When iterate_upper_bound is set, the inner C iterator keeps a pointer to the upper bound /// When iterate_upper_bound or iterate_lower_bound is set, the inner
/// inside `_readopts`. Storing this makes sure the upper bound is always alive when the /// C iterator keeps a pointer to the bounds. We need to hold onto those
/// iterator is being used. /// slices or else C iterator ends up reading freed memory.
_readopts: ReadOptions, _bounds: (Option<Vec<u8>>, Option<Vec<u8>>),
db: PhantomData<&'a D>, db: PhantomData<&'a D>,
} }
@ -96,15 +96,17 @@ impl<'a, D: DBAccess> DBRawIteratorWithThreadMode<'a, D> {
Self::from_inner(inner, readopts) Self::from_inner(inner, readopts)
} }
fn from_inner(inner: *mut ffi::rocksdb_iterator_t, readopts: ReadOptions) -> Self { fn from_inner(inner: *mut ffi::rocksdb_iterator_t, mut readopts: ReadOptions) -> Self {
// This unwrap will never fail since rocksdb_create_iterator and // This unwrap will never fail since rocksdb_create_iterator and
// rocksdb_create_iterator_cf functions always return non-null. They // rocksdb_create_iterator_cf functions always return non-null. They
// use new and deference the result so any nulls would end up in SIGSEGV // use new and deference the result so any nulls would end up in SIGSEGV
// there and we have bigger issue. // there and we have bigger issue.
let inner = std::ptr::NonNull::new(inner).unwrap(); let inner = std::ptr::NonNull::new(inner).unwrap();
let lower = readopts.iterate_lower_bound.take();
let upper = readopts.iterate_upper_bound.take();
Self { Self {
inner, inner,
_readopts: readopts, _bounds: (lower, upper),
db: PhantomData, db: PhantomData,
} }
} }

@ -336,8 +336,8 @@ pub struct BlockBasedOptions {
pub struct ReadOptions { pub struct ReadOptions {
pub(crate) inner: *mut ffi::rocksdb_readoptions_t, pub(crate) inner: *mut ffi::rocksdb_readoptions_t,
iterate_upper_bound: Option<Vec<u8>>, pub(crate) iterate_upper_bound: Option<Vec<u8>>,
iterate_lower_bound: Option<Vec<u8>>, pub(crate) iterate_lower_bound: Option<Vec<u8>>,
} }
/// Configuration of cuckoo-based storage. /// Configuration of cuckoo-based storage.

Loading…
Cancel
Save