diff --git a/crates/storage/libmdbx-rs/src/transaction.rs b/crates/storage/libmdbx-rs/src/transaction.rs index 67f28ae9e3..20e315bb38 100644 --- a/crates/storage/libmdbx-rs/src/transaction.rs +++ b/crates/storage/libmdbx-rs/src/transaction.rs @@ -412,8 +412,16 @@ impl Transaction { /// Returns a buffer which can be used to write a value into the item at the /// given key and with the given length. The buffer must be completely /// filled by the caller. + /// + /// This should not be used on dupsort tables. + /// + /// # Safety + /// + /// The caller must ensure that the returned buffer is not used after the transaction is + /// committed or aborted, or if another value is inserted. To be clear: the second call to + /// this function is not permitted while the returned slice is reachable. #[allow(clippy::mut_from_ref)] - pub fn reserve( + pub unsafe fn reserve( &self, dbi: ffi::MDBX_dbi, key: impl AsRef<[u8]>, diff --git a/crates/storage/libmdbx-rs/tests/transaction.rs b/crates/storage/libmdbx-rs/tests/transaction.rs index 81da1beada..f289b30920 100644 --- a/crates/storage/libmdbx-rs/tests/transaction.rs +++ b/crates/storage/libmdbx-rs/tests/transaction.rs @@ -105,8 +105,11 @@ fn test_reserve() { let txn = env.begin_rw_txn().unwrap(); let dbi = txn.open_db(None).unwrap().dbi(); { - let mut writer = txn.reserve(dbi, b"key1", 4, WriteFlags::empty()).unwrap(); - writer.write_all(b"val1").unwrap(); + unsafe { + // SAFETY: the returned slice is used before the transaction is committed or aborted. + let mut writer = txn.reserve(dbi, b"key1", 4, WriteFlags::empty()).unwrap(); + writer.write_all(b"val1").unwrap(); + } } txn.commit().unwrap();