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

PE解析器内层realloc()引发未定义行为的问题排查

PE解析器内层循环realloc内存错误分析与修复

问题核心原因

1. 数组索引越界破坏堆结构

你的内层循环存在内存越界访问,直接篡改了malloc的内部校验元数据,导致随机触发malloc: Incorrect checksum for freed object错误:

  • 初始时originalFirstThunkArrayIndex = 0,你给originalFirstThunkArray[0]赋值,此时数组仅分配了1个元素的空间(仅索引0有效)。
  • 进入循环后先执行originalFirstThunkArrayIndex++,索引变为1,随后调用realloc(originalFirstThunkArray, originalFirstThunkArrayIndex * sizeof(...))——仅分配1个元素的空间,但你直接访问originalFirstThunkArray[1],属于越界写操作,破坏了堆的完整性。

2. 未检查内存分配返回值

realloc分配失败时会返回NULL,如果直接用返回值覆盖原指针,会导致原内存块丢失(内存泄漏),后续访问NULL指针还会引发崩溃。

3. 循环内存分配逻辑不匹配

你希望每次新增单个结构体,但realloc的大小计算错误,没有匹配索引对应的元素数量。

修复方案

1. 修正内层循环的内存分配与访问逻辑

调整循环顺序,先扩容再更新索引,确保分配的空间足够容纳新元素:

size_t originalFirstThunkArrayIndex = 0;
struct _IMAGE_THUNK_DATA64 *originalFirstThunkArray = malloc(sizeof(struct _IMAGE_THUNK_DATA64));
if (!originalFirstThunkArray) {
    perror("malloc failed");
    free(importDescriptorArray);
    exit(EXIT_FAILURE);
}
originalFirstThunkArray[originalFirstThunkArrayIndex].u1.ordinal = some_value;

while (condition_2) {
    // 计算新内存大小:当前元素数+1
    size_t new_array_size = (originalFirstThunkArrayIndex + 1) * sizeof(struct _IMAGE_THUNK_DATA64);
    struct _IMAGE_THUNK_DATA64 *temp_ptr = realloc(originalFirstThunkArray, new_array_size);
    
    // 检查realloc是否成功
    if (!temp_ptr) {
        perror("realloc failed");
        free(originalFirstThunkArray);
        free(importDescriptorArray);
        exit(EXIT_FAILURE);
    }
    originalFirstThunkArray = temp_ptr;

    originalFirstThunkArrayIndex++;
    originalFirstThunkArrayOffset += sizeof(QWORD);
    // 此时索引对应的元素已在扩容后的有效空间内
    originalFirstThunkArray[originalFirstThunkArrayIndex].u1.ordinal = reverse_endianess_u_int64_t(readQWord(file, originalFirstThunkArrayOffset, QWORD_Buffer));
}

2. 统一修正外层循环的内存分配逻辑

外层循环同样存在类似潜在风险,建议改为初始NULL+realloc的模式,简化逻辑同时避免越界:

size_t i = 0;
struct _IMAGE_IMPORT_DESCRIPTOR64 *importDescriptorArray = NULL;

while (condition_1) {
    size_t new_desc_size = (i + 1) * sizeof(struct _IMAGE_IMPORT_DESCRIPTOR64);
    struct _IMAGE_IMPORT_DESCRIPTOR64 *temp_desc = realloc(importDescriptorArray, new_desc_size);
    if (!temp_desc) {
        perror("realloc failed");
        free(importDescriptorArray);
        free(originalFirstThunkArray);
        exit(EXIT_FAILURE);
    }
    importDescriptorArray = temp_desc;

    // 插入已修正的内层循环代码
    // ...

    i++;
}

3. 修复64位结构体定义的错误

你的IMAGE_IMPORT_DESCRIPTOR64结构体错误使用了32位的IMAGE_THUNK_DATA32,会导致PE64文件解析失败,建议修正为:

struct _IMAGE_IMPORT_DESCRIPTOR64 {
    union {
        DWORD Characteristics;
        IMAGE_THUNK_DATA64 OriginalFirstThunk; // 改为64位类型
    } u;
    DWORD timeDateStamp;
    DWORD forwarderChain;
    DWORD name;
    IMAGE_THUNK_DATA64 FirstThunk; // 改为64位类型
} IMAGE_IMPORT_DESCRIPTOR64;

额外建议

  • 所有内存分配操作后必须检查返回值,避免隐性错误。
  • 如果内存分配频率较高,可以考虑预分配一定大小的空间(比如每次扩容2倍),减少realloc调用次数,降低堆碎片化风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:30:36