Программа работает в GDB, но при запуске нормально выдает ошибку сегментации - PullRequest
0 голосов
/ 16 апреля 2020

Программа должна go пройти через все файлы в каталоге, указанном в последнем аргументе 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$

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

Основная проблема не зависела от моего кода. GDB по какой-то причине проигнорировал сигнал SIGSEGV и программа сработала. Но через несколько минут go он начал работать правильно и показывать SIGSEGV.

Но в моем коде была ошибка. Я не выделил память для entry.md5 участника, поэтому я звонил md5digest() с dest=0x0.

(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

Program received signal SIGSEGV, Segmentation fault.
__strcpy_ssse3 () at ../sysdeps/x86_64/multiarch/strcpy-ssse3.S:98
98      ../sysdeps/x86_64/multiarch/strcpy-ssse3.S: No such file or directory.
(gdb) bt
#0  __strcpy_ssse3 () at ../sysdeps/x86_64/multiarch/strcpy-ssse3.S:98
#1  0x0000000008000cc2 in md5digest (file=0x840c540, dest=0x0) at main.c:27
#2  0x0000000008000f04 in main (argc=5, argv=0x7ffffffee1c8) at main.c:56
(gdb) frame 1
#1  0x0000000008000cc2 in md5digest (file=0x840c540, dest=0x0) at main.c:27
27              strcpy((char*)dest, (char*)md5digest);
(gdb) l
22              MD5_Init(&md5handler);
23              while ((bytes = fread(data, 1, 10, file) != 0)) {
24                      MD5_Update(&md5handler, data, 10);
25              }
26              MD5_Final(md5digest, &md5handler);
27              strcpy((char*)dest, (char*)md5digest);
28      }
29
30      int main(int argc, const char** argv) {
31
(gdb) q

Все, что мне нужно было сделать - это когда добавить entry.md5 = malloc(sizeof(char) * MD5_DIGEST_LENGTH) после dbEntry entry в main()

0 голосов
/ 16 апреля 2020

Сборка программы с помощью 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 (что необходимо для завершения NUL). Исправление этой ошибки может заставить программу работать.

...