Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is pointer arithmetic the cause of a segfault?

Tags:

rust

Why is this pointer arithmetic (without reading or writing data behind these pointers) the cause of a segfault?

#![allow(dead_code,unused_variables)]
use std::cell::Cell;

struct Bar<T: ?Sized> {
    a: Cell<usize>,
    value: T,
}

unsafe fn foo<T: ?Sized>(v: &T) {
    let fake: &Bar<T> = std::mem::zeroed();

    // segfault on this line
    // we are not reading or writing uninitialized data behind the reference, 
    // but only doing pointer arithmetic. We are not reading or writing 
    // uninitialized vtable, but only copy the vtable pointer.
    let fake_val = &fake.value;
}


fn main() {
    use std::any::Any;

    let some_ref: &Any = &42 as &Any;
    unsafe { foo(some_ref) };
}

(On Playground)

Output: Segmentation fault

like image 493
chabapok Avatar asked Sep 06 '17 21:09

chabapok


2 Answers

In Rust, merely creating a dangling reference is undefined behavior! This allows the compiler to perform some aggressive optimizations around references, that wouldn't be possible otherwise.

In this particular case, the compiler generates code which calculates the offset for the field by using the align value in the vtable. So it tries to dereference the vptr which causes the segfault.


To have dangling pointer, you shouldn't use a reference, but a raw pointer. You can have dangling raw pointers without a problem!

let fake: *const Bar<T> = std::ptr::null();
like image 185
Lukas Kalbertodt Avatar answered Oct 24 '22 23:10

Lukas Kalbertodt


You are dereferencing a null pointer on the line you indicated. You are correct that you are taking a reference to that value, but the code that rustc outputs for LLVM is very stupid in debug mode. Try running this in release mode, and you'll see that probably the optimizer will be kind to you and this will no longer segfault.

Since this is UB, please don't depend on this for real code.

like image 38
Timidger Avatar answered Oct 24 '22 23:10

Timidger