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
相关产品推荐
相关产品推荐

