Skip to content

offset_of is unsound #9

@Centril

Description

@Centril

With the implementation in:

macro_rules! offset_of {
    ($parent:ty, $($field:tt)+) => (unsafe {
        let x: &'static $parent = $crate::Transmuter::<$parent> { int: 0 }.ptr;
        $crate::Transmuter { ptr: &x.$($field)+ }.int
    });
}

you are constructing a &'static T at address 0. This is undefined behavior because Rust may assume that you have a valid &'static T but you do not.

Moreover, in the old pre-1.33.0 implementation you have:

macro_rules! offset_of {
    ($father:ty, $($field:tt)+) => ({
        #[allow(unused_unsafe)]
        let root: $father = unsafe { $crate::mem::uninitialized() };

        let base = &root as *const _ as usize;

        // Future error: borrow of packed field requires unsafe function or block (error E0133)
        #[allow(unused_unsafe)]
        let member =  unsafe { &root.$($field)* as *const _ as usize };

        $crate::mem::forget(root);

        member - base
    });
}

Note that when you say &root you have already triggered undefined behavior because again, you assert with &root that you have a valid reference but you do not in fact.

See rust-lang/rfcs#2582 and rust-lang/unsafe-code-guidelines#77 for a discussion.

As for your comment about // Future error, do note that unsafe { ... } here does not make what you are doing any less undefined behavior. Instead, while you might not get an error from the compiler, you might get miscompilation should LLVM or rustc's behavior change.

cc @RalfJung

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions