You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建低内存地址(近NULL)分配的可复现CI测试用例?

可行的低内存地址缓冲区测试方案

这个问题我之前做嵌入式软件极限测试时也遇到过——通用系统的malloc()出于安全考虑,会刻意避开接近NULL的低地址区域,但要在CI测试套件里复现这个场景,其实有几个实用的方法:

1. 自定义内存分配器替换malloc()

通过钩子(hook)或者动态库注入的方式,在测试环境中替换系统默认的malloc(),直接返回你需要的低地址。

Linux/BSD 下的实现思路

用LD_PRELOAD加载一个自定义的共享库,重写malloc()函数:

#include <stdlib.h>
#include <dlfcn.h>

// 保存真实的malloc函数指针
static void* (*real_malloc)(size_t) = NULL;

void* malloc(size_t size) {
    // 只在测试模式下返回低地址,否则调用真实malloc
    if (getenv("TEST_LOW_ADDR") != NULL) {
        return (void*)0x1000;
    }
    if (!real_malloc) {
        real_malloc = dlsym(RTLD_NEXT, "malloc");
    }
    return real_malloc(size);
}

编译成共享库:gcc -shared -fPIC -o low_addr_malloc.so low_addr_malloc.c -ldl

CI运行测试时,设置环境变量加载这个库:export LD_PRELOAD=./low_addr_malloc.so; export TEST_LOW_ADDR=1; ./your_test_program

Windows 下的实现思路

可以使用_malloc_dbg或者通过Detours库来hookmalloc(),原理类似——测试时返回指定低地址,正常逻辑调用原函数。

2. 直接用内存映射(mmap)申请低地址

通用系统的malloc()不会碰低地址,但mmap()允许你指定地址分配内存,只要该地址未被系统占用。

Linux/BSD 示例

#include <sys/mman.h>
#include <stdio.h>

void* get_low_addr_buffer(size_t size) {
    void* addr = (void*)0x1000;
    void* buf = mmap(addr, size, PROT_READ | PROT_WRITE, 
                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
    if (buf == MAP_FAILED) {
        // 如果0x1000被占用,可以尝试0x2000等邻近地址
        addr = (void*)0x2000;
        buf = mmap(addr, size, PROT_READ | PROT_WRITE, 
                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
    }
    return buf;
}

MAP_FIXED参数会强制让内核使用你指定的地址(如果可用),CI环境通常是干净的,低地址大概率未被占用。测试完成后记得用munmap()释放内存。

Windows 示例

用VirtualAlloc指定地址分配:

#include <windows.h>

void* get_low_addr_buffer(size_t size) {
    void* addr = (void*)0x1000;
    void* buf = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!buf) {
        addr = (void*)0x2000;
        buf = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    }
    return buf;
}

3. 模拟低地址场景(无需真实内存)

如果你的测试只需要验证指针边界检查逻辑,不需要实际读写内存,可以直接用宏或编译选项替换malloc()的返回值:

在测试代码中添加:

#ifdef TEST_LOW_ADDR
#define malloc(size) ((void*)0x1000)
#endif

编译测试程序时加上-DTEST_LOW_ADDR,这样所有malloc()调用都会返回0x1000。这种方式最简单,适合快速验证空指针附近的逻辑漏洞。

4. 修改系统配置让malloc()分配低地址

部分系统允许调整内存分配的最低地址限制,让malloc()有可能返回接近NULL的地址:

Linux 下调整vm.mmap_min_addr

# 临时设置最低内存映射地址为0(需要root权限)
sysctl -w vm.mmap_min_addr=0
# 或者永久修改,编辑/etc/sysctl.conf添加:vm.mmap_min_addr=0

调整后,malloc()可能会分配到低地址区域。这个方法适合有root权限的CI环境(比如Docker容器),但要注意部分系统可能不允许设置为0,可尝试设为0x1000。

注意事项

  • 不要直接使用0x0(NULL地址),因为几乎所有系统都会把0页标记为不可访问,读写会直接崩溃;选0x1000、0x2000这类地址更安全。
  • 用mmap或系统配置的方法时,要先检查地址是否可用,避免分配失败影响测试。
  • CI环境要确保测试程序有足够权限(比如mmap需要普通权限,调整sysctl需要root)。

内容的提问来源于stack exchange,提问作者Cyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:02:36