Skip to content

G.SAF.MEM.03 Unsafe 模式下,应正确释放申请的内存

【级别】 要求

【描述】

当动态分配内存不再使用时应予以释放,否则会发生内存泄漏。如果攻击者可以有意触发该漏洞,则内 存资源可能被耗尽,造成拒绝服务。

优先推荐使用 RAII 模式进行内存释放,避免内存泄漏和重复释放的风险。

内存释放后,对应的指针变成悬空指针,建议重置为空指针, 一旦错误访问,可以立即得到反馈,避免 悬空指针的未定义行为(内存可能被其他业务模块重新分配,悬空指针的使用可能无意间修改了其他业务模块的数据)。

【反例】

  • 双重释放
Rust
const BUF_SIZE: usize = 100;

unsafe {
  let buf = malloc(BUF_SIZE) as *mut libc::c_char;

  // 操作指针 , 写入数据

  // 不符合:释放内存,但是指针没有设置为空
  free(buf as *mut libc::c_void);

  // ......

  // 不符合:free 内存后,指针不是空,会导致双重释放错误
  free(buf as *mut libc::c_void); 
}

【正例】

  • 双重释放
Rust
const BUF_SIZE: usize = 100;

unsafe {
  let mut buf = malloc(BUF_SIZE) as *mut libc::c_char;

  // 操作指针 , 写入数据

  // 符合:释放内存后将指针设置为 null
  if !buf.is_null() {
    free(buf as *mut c_void);
    buf = std::ptr::null_mut();
  }

  // ......

  // 符合: `ptr` 为空,不会造成双重释放错误
  if !buf.is_null() {
    free(buf as *mut c_void);
    buf = std::ptr::null_mut();
  } 
}

【反例】

  • 忘记释放
Rust
const BUF_SIZE: usize = 100;

unsafe {
  let buf = malloc(BUF_SIZE) as *mut libc::c_char;

  // 操作指针 , 写入数据

  // 不符合:忘记释放内存
}