Skip to content

C2Rust does not preserve local variable attribute((aligned)) alignment semantics #1804

@rikki322

Description

@rikki322

C2Rust does not preserve the alignment requirement of a local variable annotated with attribute((aligned(16))).
In the original C program, the local variable x is explicitly requested to be aligned to a 16-byte boundary. The program checks the address of x at runtime and prints whether it is 16-byte aligned.
After translation, C2Rust emits x as a normal Rust local variable:

let mut x: ::core::ffi::c_int = 0;

The explicit 16-byte alignment requirement is not represented in the translated Rust code. As a result, the Rust program may place x at an address that is not 16-byte aligned, causing an observable behavior difference.
To Reproduce

#include <stdio.h>

int main(void) {
    int x __attribute__((aligned(16)));
    size_t addr_x = (size_t)&x;
    int x_is_aligned_16 = (addr_x % 16 == 0);
    printf("Is aligned to 16-byte boundary: %s\n", x_is_aligned_16 ? "Yes" : "No");
    return 0;
}

Translate the program with C2Rust:

c2rust transpile test.c

C2Rust generates code:

#![allow(
    dead_code,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut
)]
extern "C" {
    fn printf(__format: *const ::core::ffi::c_char, ...) -> ::core::ffi::c_int;
}
pub type size_t = usize;
unsafe fn main_0() -> ::core::ffi::c_int {
    let mut x: ::core::ffi::c_int = 0;
    let mut addr_x: size_t = &mut x as *mut ::core::ffi::c_int as size_t;
    let mut x_is_aligned_16: ::core::ffi::c_int = (addr_x.wrapping_rem(16 as size_t)
        == 0 as size_t) as ::core::ffi::c_int;
    printf(
        b"Is aligned to 16-byte boundary: %s\n\0" as *const u8
            as *const ::core::ffi::c_char,
        if x_is_aligned_16 != 0 {
            b"Yes\0" as *const u8 as *const ::core::ffi::c_char
        } else {
            b"No\0" as *const u8 as *const ::core::ffi::c_char
        },
    );
    return 0 as ::core::ffi::c_int;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

Observed Behavior
Original C output:

Is aligned to 16-byte boundary: Yes

Translated Rust output:

Is aligned to 16-byte boundary: No

The translated program does not preserve the explicit 16-byte alignment of the local variable.
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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions