c - 程序在 GDB 中运行,但如果正常启动会引发分段错误
问题描述
程序应该遍历最后一个 CLI 参数中指定的目录中的所有文件,并将它们的名称和 MD5 和写入database
二进制文件。每次迭代一个条目。我解决了所有错误和警告,但它仍然引发分段错误。database
二进制文件保持为空,但被创建。但是,它在具有相同参数的 GDB 中工作,我可以看到database
填充数据。WSL Ubuntu 18.04
如何使其正常工作?
这是源文件:
#include <dirent.h>
#include <openssl/md5.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
typedef struct dbEntry {
unsigned int id;
char* name;
char* type;
unsigned int parent_id;
unsigned char* md5;
} dbEntry;
void md5digest(FILE* file, unsigned char* dest) {
MD5_CTX md5handler;
int bytes;
void* data = 0;
unsigned char md5digest[MD5_DIGEST_LENGTH];
MD5_Init(&md5handler);
while ((bytes = fread(data, 1, 10, file) != 0)) {
if (data != 0){
MD5_Update(&md5handler, data, 10);
}
}
MD5_Final(md5digest, &md5handler);
strcpy((char*)dest, (char*)md5digest);
}
int main(int argc, const char** argv) {
if (strcmp(argv[1], "-s") == 0 && strcmp(argv[2], "-f") == 0 &&
argc == 5) {
FILE* database = fopen(argv[3], "ab+");
DIR* dir = opendir(argv[4]);
struct dirent* dirent = readdir(dir);
unsigned int id = 0;
dbEntry entry;
while (dirent != NULL) {
if (dirent->d_type == 8) {
entry.id = id;
entry.name = dirent->d_name;
entry.type = "file";
entry.parent_id = 0;
const size_t len = strlen(argv[4]) + strlen(entry.name);
char* fpath = malloc(sizeof(char)*len);
strcpy(fpath, argv[4]);
strcat(fpath, entry.name);
printf("%s\n", fpath);
FILE* file = fopen(fpath, "rb");
if (file != NULL){
md5digest(file, entry.md5);
fclose(file);
fwrite(&entry, sizeof(dbEntry), 1, database);
}
else{
printf("Error opening file %s\n", entry.name);
fpath[0] = '\0';
}
id++;
}
dirent = readdir(dir);
}
fclose(database);
}
return 0;
}
GDB 输出:
altbrace@altbrace-PC:~/csc-integrctrl/src$ ls -lh
total 148K
-rw-rw-rw- 1 altbrace altbrace 0 Apr 16 22:14 database
-rwxrwxrwx 1 altbrace altbrace 63K Apr 16 22:09 integrctrl
-rw-rw-rw- 1 altbrace altbrace 1.6K Apr 16 22:09 main.c
altbrace@altbrace-PC:~/csc-integrctrl/src$ gdb ./integrctrl
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./integrctrl...done.
(gdb) set args -s -f database /home/altbrace/
(gdb) r
Starting program: /home/altbrace/csc-integrctrl/src/integrctrl -s -f database /home/altbrace/
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
/home/altbrace/.bash_history
/home/altbrace/.bash_logout
/home/altbrace/.bashrc
/home/altbrace/.bashrc.backup
/home/altbrace/.gitconfig
/home/altbrace/.mysql_history
Error opening file .mysql_history
/home/altbrace/.profile
/home/altbrace/.python_history
/home/altbrace/.sudo_as_admin_successful
/home/altbrace/.viminfo
/home/altbrace/.vimrc
/home/altbrace/.wget-hsts
/home/altbrace/Makefile
/home/altbrace/main.c
/home/altbrace/test.py
[Inferior 1 (process 18767) exited normally]
(gdb) q
altbrace@altbrace-PC:~/csc-integrctrl/src$ ls -lh
total 148K
-rw-rw-rw- 1 altbrace altbrace 560 Apr 16 22:14 database
-rwxrwxrwx 1 altbrace altbrace 63K Apr 16 22:09 integrctrl
-rw-rw-rw- 1 altbrace altbrace 1.6K Apr 16 22:09 main.c
分段故障:
altbrace@altbrace-PC:~/csc-integrctrl/src$ ls -lh
total 148K
-rw-rw-rw- 1 altbrace altbrace 560 Apr 16 22:14 database
-rwxrwxrwx 1 altbrace altbrace 63K Apr 16 22:09 integrctrl
-rw-rw-rw- 1 altbrace altbrace 2.2K Apr 16 23:32 main.c
altbrace@altbrace-PC:~/csc-integrctrl/src$ rm database
altbrace@altbrace-PC:~/csc-integrctrl/src$ ./integrctrl -s -f database /home/altbrace/
/home/altbrace/.bash_history
Segmentation fault (core dumped)
altbrace@altbrace-PC:~/csc-integrctrl/src$
解决方案
构建程序gcc -g t.c -lcrypto -fsanitize=address
显示它有一个堆缓冲区溢出:
=================================================================
==77421==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x607000000144 at pc 0x7f92565d35f3 bp 0x7fff262b40a0 sp 0x7fff262b3850
WRITE of size 65 at 0x607000000144 thread T0
#0 0x7f92565d35f2 in __interceptor_strcat (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xa95f2)
#1 0x55d3cc70f84c in main /tmp/t.c:49
#2 0x7f92560a5bba in __libc_start_main ../csu/libc-start.c:308
#3 0x55d3cc70f219 in _start (/tmp/a.out+0x1219)
0x607000000144 is located 0 bytes to the right of 68-byte region [0x607000000100,0x607000000144)
allocated by thread T0 here:
#0 0x7f9256631538 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107538)
#1 0x55d3cc70f7ef in main /tmp/t.c:47
#2 0x7f92560a5bba in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xa95f2) in __interceptor_strcat
您忘记添加 1 len
(这是 terminating 所需的NUL
)。修复此错误可能会使程序正常工作。
推荐阅读
- linux - 如何为特定内核版本的 liveCD 创建 initrd.img 文件
- jmeter - 使用多个用户在不同时间段内使用相同数量的事务运行 JMeter 测试
- python-3.x - Python Flask:参数中的库变量
- python - 有没有办法从 sqlite db 以有组织的形式获取数据?
- regex - 使用 match() 匹配特定的正则表达式
- java - 切换布局时固定背景
- sql - Oracle SQL,一张大表分类列和百分比分布
- eclipse - Eclipse 非阻塞完成被忽略
- glpk - 线性形式的乘法不允许错误
- java - 使用 SessionFactory 时事务管理在 neo4j-omg 中不起作用