-
Notifications
You must be signed in to change notification settings - Fork 146
Open
Description
The following code panics as of ipc-channel 0.19.0:
use ipc_channel::ipc::{IpcSharedMemory, channel};
use std::iter;
fn main() {
let regions: Vec<IpcSharedMemory> = iter::repeat_n(b"foobar".as_slice(), 65)
.map(IpcSharedMemory::from_bytes)
.collect();
let (sender, receiver) = channel().unwrap();
sender.send(regions).unwrap();
receiver.recv().unwrap();
}Full Backtrace
thread 'main' panicked at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:562:78:
index out of bounds: the len is 64 but the index is 64
stack backtrace:
0: rust_begin_unwind
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/std/src/panicking.rs:695:5
1: core::panicking::panic_fmt
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/panicking.rs:75:14
2: core::panicking::panic_bounds_check
at /rustc/05f9846f893b09a1be1fc8560e33fc3c815cfecb/library/core/src/panicking.rs:273:5
3: <usize as core::slice::index::SliceIndex<[T]>>::index_mut
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:280:14
4: core::slice::index::<impl core::ops::index::IndexMut<I> for [T]>::index_mut
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:27:9
5: <alloc::vec::Vec<T,A> as core::ops::index::IndexMut<I>>::index_mut
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3370:9
6: <ipc_channel::ipc::IpcSharedMemory as serde::de::Deserialize>::deserialize::{{closure}}
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:562:78
7: std::thread::local::LocalKey<T>::try_with
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:310:12
8: std::thread::local::LocalKey<T>::with
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:274:15
9: <ipc_channel::ipc::IpcSharedMemory as serde::de::Deserialize>::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:558:32
10: <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.219/src/de/mod.rs:800:9
11: <<&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_tuple::Access<R,O> as serde::de::SeqAccess>::next_element_seed
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/de/mod.rs:314:25
12: serde::de::SeqAccess::next_element
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.219/src/de/mod.rs:1734:9
13: <serde::de::impls::<impl serde::de::Deserialize for alloc::vec::Vec<T>>::deserialize::VecVisitor<T> as serde::de::Visitor>::visit_seq
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.219/src/de/impls.rs:1175:46
14: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_tuple
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/de/mod.rs:326:9
15: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_seq
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/de/mod.rs:350:9
16: serde::de::impls::<impl serde::de::Deserialize for alloc::vec::Vec<T>>::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.219/src/de/impls.rs:1186:9
17: <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.219/src/de/mod.rs:800:9
18: bincode::internal::deserialize_seed
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/internal.rs:118:15
19: bincode::internal::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/internal.rs:106:5
20: bincode::config::Options::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/config/mod.rs:200:9
21: bincode::deserialize
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bincode-1.3.3/src/lib.rs:181:5
22: ipc_channel::ipc::IpcMessage::to::{{closure}}::{{closure}}
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:726:34
23: std::thread::local::LocalKey<T>::try_with
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:310:12
24: std::thread::local::LocalKey<T>::with
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:274:15
25: ipc_channel::ipc::IpcMessage::to::{{closure}}
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:713:13
26: std::thread::local::LocalKey<T>::try_with
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:310:12
27: std::thread::local::LocalKey<T>::with
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:274:15
28: ipc_channel::ipc::IpcMessage::to
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:712:9
29: ipc_channel::ipc::IpcReceiver<T>::recv
at /home/alaska/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ipc-channel-0.19.0/src/ipc.rs:254:9
30: ipc_test::main
at ./src/main.rs:10:5
31: core::ops::function::FnOnce::call_once
at /home/alaska/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
The problem is that the receiver expects to receive at most 64 file descriptors (one of which may be reserved for fragmented messages).
The IpcSender has no such limit and will happily send as many file descriptors as you give it. (In the example above, one IpcSharedMemory is one fd). This causes the file descriptors to be lost, so the deserialization code panics when they're not there.
Relevant sections of the code are
ipc-channel/src/platform/unix/mod.rs
Line 44 in 1e6db1c
| const MAX_FDS_IN_CMSG: u32 = 64; |
ipc-channel/src/platform/unix/mod.rs
Lines 374 to 393 in 1e6db1c
| // If the message is small enough, try sending it in a single fragment. | |
| if data.len() <= Self::get_max_fragment_size() { | |
| match send_first_fragment(self.fd.0, &fds[..], data, data.len()) { | |
| Ok(_) => return Ok(()), | |
| Err(error) => { | |
| // ENOBUFS means the kernel failed to allocate a buffer large enough | |
| // to actually transfer the message, | |
| // although the message was small enough to fit the maximum send size -- | |
| // so we have to proceed with a fragmented send nevertheless, | |
| // using a reduced send buffer size. | |
| // | |
| // Any other errors we might get here are non-recoverable. | |
| if !(matches!(error, UnixError::Errno(libc::ENOBUFS)) | |
| && downsize(&mut sendbuf_size, data.len()).is_ok()) | |
| { | |
| return Err(error); | |
| } | |
| }, | |
| } | |
| } |
This was first discovered in servo/servo#36792.