Change the return type of SharedMemory::data (#5240)

This commit is an attempt at improving the safety of using the return
value of the `SharedMemory::data` method. Previously this returned
`*mut [u8]` which, while correct, is unwieldy and unsafe to work with.
The new return value of `&[UnsafeCell<u8>]` has a few advantages:

* The lifetime of the returned data is now connected to the
  `SharedMemory` itself, removing the possibility for a class of errors
  of accidentally using the prior `*mut [u8]` beyond its original lifetime.

* It's not possibly to safely access `.len()` as opposed to requiring an
  `unsafe` dereference before.

* The data internally within the slice is now what retains the `unsafe`
  bits, namely indicating that accessing any memory inside of the
  contents returned is `unsafe` but addressing it is safe.

I was inspired by the `wiggle`-based discussion on #5229 and felt it
appropriate to apply a similar change here.
This commit is contained in:
Alex Crichton
2022-11-10 11:51:10 -06:00
committed by GitHub
parent 5b6d5e78de
commit 2be457c295
3 changed files with 34 additions and 17 deletions

View File

@@ -65,15 +65,22 @@ fn test_sharing_of_shared_memory() -> Result<()> {
let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 5))?;
let instance1 = Instance::new(&mut store, &module, &[shared_memory.clone().into()])?;
let instance2 = Instance::new(&mut store, &module, &[shared_memory.clone().into()])?;
let data = shared_memory.data();
// Modify the memory in one place.
unsafe {
(*(shared_memory.data()))[0] = 42;
*data[0].get() = 42;
}
// Verify that the memory is the same in all shared locations.
let shared_memory_first_word =
i32::from_le_bytes(unsafe { (*shared_memory.data())[0..4].try_into()? });
let shared_memory_first_word = i32::from_le_bytes(unsafe {
[
*data[0].get(),
*data[1].get(),
*data[2].get(),
*data[3].get(),
]
});
let instance1_first_word = instance1
.get_typed_func::<(), i32, _>(&mut store, "first_word")?
.call(&mut store, ())?;