Skip to content

We are computing the wrong offset for unsized packed structs #118537

Closed

Description

This code panics, but it should not:

use std::mem;

struct Slice([u32]);

#[repr(packed, C)]
struct PackedSized {
    f: u8,
    d: [u32; 4],
}

#[repr(packed, C)]
struct PackedUnsized {
    f: u8,
    d: Slice,
}

impl PackedSized {
    fn unsize(&self) -> &PackedUnsized {
        // We can't unsize via a generic type since then we get the error
        // that packed structs with unsized tail don't work if the tail
        // might need dropping.
        let len = 4usize;
        unsafe { mem::transmute((self, len)) }
    }
}

fn main() { unsafe {
    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
    let p = p.unsize() as *const PackedUnsized;
    let d = std::ptr::addr_of!((*p).d);
    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
} }

The panic disappears when the Newtype is inlined (because then we hit a different code path in this match).

What happens here is a bug in the logic that computes the offset of d: since it is an unsized field, the offset is computed dynamically, by taking the statically known offset and then rounding it up to the dynamic alignment of the field. However, since the struct is packed, we need to cap the dynamic alignment of the field to the packing of the surrounding struct -- which we currently do not do. This is just yet another case where the non-compositional nature of repr(packed) is causing issues...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-layoutArea: Memory layout of typesC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions