Skip to content

G.SAF.FFI.02 在 FFI 调用的场景下,应确保跨边界数据的内存布局兼 容

【级别】 要求

【描述】

FFI 函数传递的任何数据类型,需要保证内存布局一致。对于结构体、枚举和联合体,应该通过添加 # [repr(C)] 属性,来避免字段顺序重排,以保证内存布局的兼容。 在处理网络消息收发场景中,常见 1 字节对齐内存布局方式。在 Rust 中可以使用 #[repr(packed)] 表示对应的数据。

【正例】

Rust
#[repr(C)]
struct Foo {
  a: libc::c_short, 
  b: libc::c_int,
  c: libc::c_char, 
  d: libc::c_long,
}

#[link(name = "bar")] extern "C" {
  fn bar(foo: *const Foo); 
}

fn main() {
  let foo = Foo { 
    a: 1234,
    b: 12345, 
    c: 123,
    d: 123456, 
  };
  unsafe {
    bar(&foo as *const Foo); 
  }
}

【正例】

Rust
#[repr(packed)]  
#[derive(Debug)] 
struct Foo {
  a: libc::c_char, 
  b: libc::c_int,
  c: libc::c_longlong,
}

extern "C" {
  fn new_foo() -> Foo;
}

let foo = unsafe { new_foo() }; 
println!("{foo:?}");
#pragma pack(1)
typedef struct Foo { 
  char a;
  int b;
  long long c; 
} Foo;
#pragma pack()

struct Foo new_foo() {
  struct Foo foo = {'c', 1234, 123456789}; 
  return foo;
}