G.SAF.MEM.01 应校验内存申请函数的输入参数和返回值
【级别】 要求
【描述】
涉及内存分配的函数调用,应注意:
- 申请前应校验申请大小
当申请内存大小由程序外部输入时,内存申请前,要求对申请内存大小进行合法性校验,防止申请 0 长度内存,或过多地、非法地申请内存。
- 申请后应校验是否成功
当申请内存的数值过大(可能一次就申请了非常大的超预期的内存;也可能循环中多次申请内 存),可能会造成内存申请失败,返回空指针。
【反例】
申请前应校验申请大小
Rust
// CWE-789
fn get_untrusted_size() -> usize {
//返回外部函数确定的大小
unsafe { other_lib_get_size() }
}
fn main() {
let size = get_untrusted_size();
// 不符合:内存分配 size 由外部传入,没有检查其值是否过大
let buffer: Vec<u8> = Vec::with_capacity(size);
// receive external data with buffer...
}
【正例】
申请前应校验申请大小
Rust
fn get_untrusted_size() -> usize {
//返回外部函数确定的大小
unsafe { other_lib_get_size() }
}
fn main() {
const BUF_MAX_SIZE: usize = 2_usize.pow(8);
let size = BUF_MAX_SIZE.min(get_untrusted_size());
// 符合:给外部传入的内存分配 size 值设定了一个上限
let buffer: Vec<u8> = Vec::with_capacity(size);
// receive external data with buffer...
}
【反例】
申请后应校验是否成功
Rust
fn func() {
let malloc_size = || usize::MAX;
// 不符合:未校验内存分配函数的参数
let ptr = unsafe { libc::malloc(malloc_size()) };
// 使用 ptr 进行内存操作
// ...
unsafe { libc::free(ptr) };
}
【正例】
申请后应校验是否成功
Rust
fn func() {
let malloc_size = || usize::MAX;
let ptr = unsafe { libc::malloc(malloc_size()) };
if !ptr.is_null() {
// 使用 ptr 进行内存操作
// ...
unsafe { libc::free(ptr) };
}
}