Skip to content

C2Rust generates unaligned reference when taking address of packed struct field C2Rust incorrectly translates taking the address of a field in a attribute((packed)) struct. #1678

@lynae99

Description

@lynae99

In C, taking the address of a packed field is allowed, even though the resulting pointer may be unaligned. The following program simply computes the byte offset of a field inside a packed struct by subtracting two addresses.
However, C2Rust generates Rust code that creates a reference to the packed field (&mut p.b), which is not allowed in Rust because packed struct fields may be unaligned. As a result, the generated code fails to compile with an unaligned reference error.
Reproducer

#include <stdint.h>

struct __attribute__((packed)) Packed {
    uint8_t a;
    uint32_t b;
};

int main(void) {
    struct Packed p = {0};
    int offset = (int)((uintptr_t)&p.b - (uintptr_t)&p);
    return offset;
}

Transpiled Rust

#![allow(
    dead_code,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut
)]
pub type __uint8_t = u8;
pub type __uint32_t = u32;
pub type uint8_t = __uint8_t;
pub type uint32_t = __uint32_t;
pub type uintptr_t = usize;
#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct Packed {
    pub a: uint8_t,
    pub b: uint32_t,
}
unsafe fn main_0() -> ::core::ffi::c_int {
    let mut p: Packed = {
        let mut init = Packed { a: 0 as uint8_t, b: 0 };
        init
    };
    let mut offset: ::core::ffi::c_int = (&mut p.b as *mut uint32_t as uintptr_t)
        .wrapping_sub(&mut p as *mut Packed as uintptr_t) as ::core::ffi::c_int;
    return offset;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

Observed Behavior
The generated Rust code fails to compile:

error: reference to packed field is unaligned

This happens because the generated code creates a reference to a packed field:

&mut p.b

Creating references to packed fields is undefined behavior in Rust.
Environment

  • c2rust version: v0.21.0
  • platform: Ubuntu 24.04
  • Rust: nightly-2022-08-08
  • Clang version: 17.0.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions