Skip to content

G.MAC.PRO.01 不应通过过程宏将 unsafe 代码包装为 safe 代码

【级别】 要求

【描述】

不要通过过程宏将 unsafe 代码包装为safe 代码,以此来规避 Rust 静态分析检查。

【反例】

Rust
// 用 RUST 的过程宏包装 libc 的函数 printf 来打印一个 C 字符串
// 这个宏的输入参数必须是一个有效的 C 字符串指针,整个宏的使用是不安全的, // 但是因为过程宏中包括了 unsafe,导致过程宏看起来像 safe 调用
//
// rprintf!(b"hello\0" as *const u8);

#[proc_macro]
pub fn rprintf(input: TokenStream) -> TokenStream {
  let expr = parse_macro_input!(input as syn::Expr);
  // 这里包括 unsafe 代码,这样整个宏可以在 safe 代码中使用
  quote!({
    unsafe {
      printf(b"%s\n\0" as *const _ as *const u8, #expr); 
    }
  }).into() 
}

【正例】

Rust
// 用 RUST 的过程宏包装 libc 的函数 printf 来打印一个 C 字符串
// 这个宏的输入参数必须是一个有效的 C 字符串指针,同时也是调用外部函数 // 必须在 unsafe 代码块中使用
//
// unsafe { rprintf!(b"hello\0" as *const u8) };

#[proc_macro]
pub fn rprintf(input: TokenStream) -> TokenStream {
  let expr = parse_macro_input!(input as syn::Expr);
  // 这里不能包括 unsafe 代码,而是要求整个宏在 unsafe 代码块中使用
  quote!({
    printf(b"%s\n\0" as *const _ as *const u8, #expr); 
  }).into()
}

【相关讨论】