求助:修复C代码中的heap-buffer-overflow(堆缓冲区溢出)错误
修复AddressSanitizer堆缓冲区溢出错误
错误原因分析
ASAN报的heap-buffer-overflow出现在strchr调用时,说明程序在查找换行符时读取了超出data堆缓冲区范围的内存。大概率是以下两种情况之一:
- 传入
processData的data不是以'\0'终止的合法C字符串(比如用read()读取文件内容后未手动添加终止符),导致strchr会一直向后扫描,直到越界访问堆内存。 - 循环逻辑只处理带换行符的行,未处理无换行符的最后一行,且当
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
相关产品推荐
相关产品推荐

