mohrezaei/thincollections

Segmentation fault cloning an empty ThinVec

Closed this issue · 9 comments

I encountered a segfault trying to initialize with vec![thinvec![]; N], which I managed to reproduce with a simple clone. In debug mode this runs fine, but it fails with optimizations on.

extern crate thincollections;

use thincollections::thin_vec::ThinVec;

fn main() {
    let v = ThinVec::<usize>::new();
    let _v = v.clone();
}

I added [profile.release] debug = true and gathered crash details with GDB:

Program received signal SIGSEGV, Segmentation fault.
<thincollections::thin_vec::ThinVec<T> as core::ops::deref::Deref>::deref (self=<optimized out>)
    at /home/jistone/.cargo/registry/src/github.com-1ecc6299db9ec823/thincollections-0.5.1/src/thin_vec.rs:1709
1709                    len = *len_ptr;
Missing separate debuginfos, use: dnf debuginfo-install libgcc-8.2.1-4.fc28.x86_64
(gdb) p len_ptr
$1 = (usize *) 0xffffffffffffffff
(gdb) bt
#0  <thincollections::thin_vec::ThinVec<T> as core::ops::deref::Deref>::deref (self=<optimized out>)
    at /home/jistone/.cargo/registry/src/github.com-1ecc6299db9ec823/thincollections-0.5.1/src/thin_vec.rs:1709
#1  <thincollections::thin_vec::ThinVec<T> as core::clone::Clone>::clone (self=0x7fffffffd178)
    at /home/jistone/.cargo/registry/src/github.com-1ecc6299db9ec823/thincollections-0.5.1/src/thin_vec.rs:2327
#2  0x000055555555a45e in thin::main () at src/main.rs:7
$ rustc -Vv
rustc 1.30.0 (da5f414c2 2018-10-24)
binary: rustc
commit-hash: da5f414c2c0bfe5198934493f04c676e2b23ff2e
commit-date: 2018-10-24
host: x86_64-unknown-linux-gnu
release: 1.30.0
LLVM version: 8.0

Perhaps related, cargo test --release on this crate dies with SIGILL in stable_thinvec_tests.

Thanks for the report! I'll have a look.

I believe the problem is the use of ptr::null_mut() to construct the empty slice.

https://doc.rust-lang.org/stable/std/slice/fn.from_raw_parts.html

data must be non-null and aligned, even for zero-length slices.

The use of 1 as *const T and 1 as *mut T elsewhere also fails the alignment requirement. I think a better choice would be NonNull::dangling().as_ptr().

I'll give that a try. It's odd, because that code is all over std::Vec.

Maybe the alignment is not a big deal (yet), but non-null is definitely important for slices. Such references are given the nonnull attribute in LLVM IR, and optimizations can make heavy assumptions based on this.

Fixed in 58739fd
Thanks for the report and the solution. I did change all the 1 as cases. They only occur for ZST types, so maybe that's why it just worked.

Published 0.5.2 with the fix.

Thanks!

FYI, your v0.5.1 and v0.5.2 git tags are pointing to the same commit 5376415 as v0.5.0. The actual published crate does appear to be correct though. (edited because I pasted the wrong commit ID too...)

Yes, in all my excitement I forgot a step. I think I've pushed the right tag versions now. Thanks for the heads up.