ipc-channel
ipc-channel copied to clipboard
macos::OsIpcSharedMemory::from_bytes aborts if passed an empty slice
* thread #43, stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
frame #0: 0x000000011ba94c29 servo`core::intrinsics::copy_nonoverlapping::h64863016c6ffb52b(src="", dst=0x0000000000000000, count=0) at intrinsics.rs:2125:9
2122 && is_nonoverlapping(src, dst, count))
2123 {
2124 // Not panicking to keep codegen impact smaller.
-> 2125 abort();
2126 }
2127
2128 // SAFETY: the safety contract for `copy_nonoverlapping` must be
Target 0: (servo) stopped.
(lldb) li -
2115 extern "rust-intrinsic" {
2116 fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
2117 }
2118
2119 if cfg!(debug_assertions)
2120 && !(is_aligned_and_not_null(src)
2121 && is_aligned_and_not_null(dst)
(lldb) up
frame #1: 0x000000011b2685cf servo`ipc_channel::platform::macos::OsIpcSharedMemory::from_bytes::h04f07f4eb147b3e9(bytes=(data_ptr = "", length = 0)) at mod.rs:900:13
897 pub fn from_bytes(bytes: &[u8]) -> OsIpcSharedMemory {
898 unsafe {
899 let address = allocate_vm_pages(bytes.len());
-> 900 ptr::copy_nonoverlapping(bytes.as_ptr(), address, bytes.len());
901 OsIpcSharedMemory::from_raw_parts(address, bytes.len())
902 }
903 }
(lldb) up
frame #2: 0x000000011b2197bd servo`ipc_channel::ipc::IpcSharedMemory::from_bytes::h23c8b06c54dcec83(bytes=(data_ptr = "", length = 0)) at ipc.rs:509:31
506 /// Create shared memory initialized with the bytes provided.
507 pub fn from_bytes(bytes: &[u8]) -> IpcSharedMemory {
508 IpcSharedMemory {
-> 509 os_shared_memory: OsIpcSharedMemory::from_bytes(bytes),
510 }
511 }
512
The root here is that allocate_vm_pages can return a null pointer. We should probably make it return Option<NonNull<u8> instead and force callers to deal with that appropriately.