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

求助:修复C代码中的heap-buffer-overflow(堆缓冲区溢出)错误

修复AddressSanitizer堆缓冲区溢出错误

错误原因分析

ASAN报的heap-buffer-overflow出现在strchr调用时,说明程序在查找换行符时读取了超出data堆缓冲区范围的内存。大概率是以下两种情况之一:

  1. 传入processData的data不是以'\0'终止的合法C字符串(比如用read()读取文件内容后未手动添加终止符),导致strchr会一直向后扫描,直到越界访问堆内存。
  2. 循环逻辑只处理带换行符的行,未处理无换行符的最后一行,且当data无终止符时触发越界。

修复方案

1. 确保输入字符串正确终止

如果data是从文件读取的,比如用read()系统调用,必须在读取完成后手动添加字符串终止符:

// 示例:读取文件到堆内存并确保终止
int fd = open("data.csv", O_RDONLY);
off_t file_size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
char *data = malloc(file_size + 1); // 多分配1字节存'\0'
if (data == NULL) { /* 处理内存分配失败 */ }
ssize_t bytes_read = read(fd, data, file_size);
data[bytes_read] = '\0'; // 手动添加终止符
close(fd);
processData(data);
free(data);

2. 修改循环逻辑,覆盖所有行(包括无换行符的最后一行)

原循环仅处理包含\n的行,且未检查字符串是否终止,修改为覆盖所有行的逻辑:

void processData(char *data) {
    char *string = data;
    // 循环条件改为检查当前位置是否为字符串终止符
    while (string != NULL && *string != '\0') {
        char *line = strchr(string, '\n');
        size_t line_len;

        if (line != NULL) {
            line_len = line - string;
        } else {
            // 处理最后一行:无换行符,用strlen获取长度(前提是data已终止)
            line_len = strlen(string);
        }

        // 分配内存存储单行内容,+1用于终止符
        char *aux = malloc(line_len + 1);
        if (aux == NULL) {
            perror("malloc failed");
            break;
        }
        memcpy(aux, string, line_len);
        aux[line_len] = '\0'; // 确保单行是合法C字符串

        loadData(aux);

        free(aux);

        // 更新指针到下一行
        if (line != NULL) {
            string = line + 1;
        } else {
            break; // 已处理到最后一行,退出循环
        }
    }
}

额外检查点

  • 确认data的堆内存分配大小足够:必须是实际内容长度+1(用于存储\0)。
  • 如果data是栈分配的,也要确保它以\0结尾,且不会超出栈缓冲区范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:10:16