SIGABRT in C Linux - c

i received an strange SIGABRT in my C program, tha's my function where the problem appears:
int get_interface_mac_addr(Interface* iface) {
char arquivo[10];
sprintf(arquivo, "/sys/class/net/%s/address", iface->interface_name);
int fd;
fd = open(arquivo, O_RDONLY, 0);
char buf[100];
read(fd, buf, sizeof (buf));
buf[strlen(buf) - 1] = '\0';
strcpy(iface->interface_mac_addr, buf);
close(fd);
return GET_MAC_ADDR_SUCCESS;
}
The error happends at "}", the last line of code.
I try to debug with GDB, but I'm new at this, so I do not understand many things that GDB tells me. Below is the output from GDB:
Core was generated by `./vfirewall-monitor'.
Program terminated with signal 6, Aborted.
#0 0x00007f36c043b425 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007f36c043b425 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007f36c043eb8b in __GI_abort () at abort.c:91
#2 0x00007f36c047939e in __libc_message (do_abort=2, fmt=0x7f36c058157f "*** %s ***: %s terminated\n")
at ../sysdeps/unix/sysv/linux/libc_fatal.c:201
#3 0x00007f36c050ff47 in __GI___fortify_fail (msg=0x7f36c0581567 "stack smashing detected") at fortify_fail.c:32
#4 0x00007f36c050ff10 in __stack_chk_fail () at stack_chk_fail.c:29
#5 0x00000000004029be in get_interface_mac_addr (iface=0x7f36b4004560) at interfaces.c:340
#6 0x00000000004022c9 in get_interfaces_info (iface=0x7f36b4004560) at interfaces.c:87
#7 0x0000000000402d9d in get_all_system_info () at kernel.c:109
#8 0x00007f36c07cce9a in start_thread (arg=0x7f36bb729700) at pthread_create.c:308
#9 0x00007f36c04f93fd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#10 0x0000000000000000 in ?? ()
(gdb)
Someone know whats going on in this case? I do something wrong and a can see what is?
many thanks.

char arquivo[10]; // <-- here
sprintf(arquivo, "/sys/class/net/%s/address", iface->interface_name);
arquivo is way too small for that string.
You should also check the return value of open():
fd = open(arquivo, O_RDONLY, 0);
if(fd < 0) {
perror("open");
// do something
}
This also wrong:
read(fd, buf, sizeof (buf));
buf[strlen(buf) - 1] = '\0';
^^^^^^^^^^^
read() does not null terminate anything. You can't call strlen() on buf. Instead:
int n = read(fd, buf, sizeof (buf));
if(n < 0) {
perror("read");
// do something
}
buf[n] = '\0';

Related

web server returns segfault when reloading webpage constantly + other error

I'm making a C web server on my raspberry pi and I've come across a problem where when I constantly reload the webpage, the web server gives me a segmentation fault. It also sometimes refuses to run the threads after a while of constant traffic. I used gdb to debug the segfault and this is what I found:
Thread 145 "webServer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x6f59b440 (LWP 21885)]
memcpy () at ../sysdeps/arm/memcpy.S:196
196 ../sysdeps/arm/memcpy.S: No such file or directory.
(gdb) where
#0 memcpy () at ../sysdeps/arm/memcpy.S:196
#1 0xb6e94b48 in __GI__IO_file_xsgetn (fp=0x52719f08, data=<optimized out>,
n=1) at fileops.c:1303
#2 0xb6e87df8 in __GI__IO_fread (buf=0x2343c <fileLine>, size=1, count=1,
fp=0x52719f08) at iofread.c:38
#3 0x000114c4 in handleClient (pClientSock=0x23830 <clientSock>)
at webServer.c:242
#4 0x000116a0 in giveThreadWork () at webServer.c:298
#5 0xb6f7f494 in start_thread (arg=0x6f59b440) at pthread_create.c:486
#6 0xb6f02568 in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:73
from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
I couldn't find anything for the refusing threads though.
It says that there are some problems on lines: 242 and 298. All there is there, is the following:
Line 242-266
============
while ((freadErr = fread(fileLine, sizeof(fileLine), 1, fpointer)) != 0) {
if (freadErr < 0) {
printf("fread error\n");
perror("fread");
close(acceptSock);
memset_all();
return NULL;
}
if ((send(acceptSock, httpResponse, strlen(httpResponse), MSG_NOSIGNAL)) == -1) {
printf("write error1\n");
perror("we1");
close(acceptSock);
memset_all();
return NULL;
}
if ((send(acceptSock, fileLine, sizeof(fileLine), MSG_NOSIGNAL)) == -1) {
printf("write error2\n");
perror("we2");
close(acceptSock);
memset_all();
return NULL;
}
memset(fileLine, 0, 1);
memset(httpResponse, 0, 1000);
line 285-304 (298 is where error is)
==================
void *giveThreadWork() {
while (1) {
int *pclient;
pthread_mutex_lock(&mutex);
if ((pclient = dequeue()) == NULL) {
pthread_cond_wait(&condition_var, &mutex);
pclient = dequeue();
}
pthread_mutex_unlock(&mutex);
if (pclient != NULL) {
handleClient(pclient);
} else {
printf("\n\n\n\n\n no more listener \n\n\n\n\n");
close(*pclient);
}
}
}
I can't get anymore info from gdb but maybe someone else knows how. I've tried changing the strcpy() functions and checked all the string manipulation functions (or i'm pretty sure I have) and I've found nothing.
Here is all the code if anyone needs it: https://www.toptal.com/developers/hastebin/xokipuvidu.c
Hopefully someone can help or point me in the right direction

How to use threads with libev

I'm making a webcrawler and want to spawn a number of threads each with its own event loop to monitor network activity. Here is my code so far:
static void my_cb(EV_P_ struct ev_io *w, int revents)
{
GlobalInfo *g = (GlobalInfo *)w->data;
i = 0;
if (g->concurrent_connections < MAX_CONNECTIONS)
{
while (i < MAX_LOAD && i < MAX_CONNECTIONS - g->concurrent_connections)
{
add_url(g);
}
}
}
static int init(GlobalInfo *g)
{
int fd;
fd = open("myfile", O_RDWR | O_NONBLOCK, 0);
if(fd == -1) {
perror("open");
exit(1);
}
g->input = fdopen(fd, "r");
ev_io_init(&g->fifo_event, my_cb, fd, EV_READ);
ev_io_start(g->loop, &g->fifo_event);
}
void *crawler(void *threadid)
{
GlobalInfo g;
long tid;
tid = (long)threadid;
printf("Initalised thread #%ld!\n", tid);
memset(&g, 0, sizeof(GlobalInfo));
g.loop = ev_loop_new(EVFLAG_AUTO);
g.done = 0;
g.downloaded = 0;
g.head = 0;
g.added = 0;
g.concurrent_connections = 0;
init(&g);
g.multi = curl_multi_init();
ev_timer_init(&g.timer_event, timer_cb, 0., 0.);
g.timer_event.data = &g;
g.fifo_event.data = &g;
curl_multi_setopt(g.multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g);
curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g);
/* we don't call any curl_multi_socket*() function yet as we have no handles
added! */
ev_loop(g.loop, 0);
curl_multi_cleanup(g.multi);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
mysql_start();
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
rc = pthread_create(&threads[t], NULL, crawler, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
mysql_stop();
mysql_library_end();
return 0;
}
As you can see I attempt to make a new event loop in each thread with ev_loop_new. However, the program aborts with the following backtrace:
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff75bb859 in __GI_abort () at abort.c:79
#2 0x00007ffff76263ee in __libc_message (action=action#entry=do_abort, fmt=fmt#entry=0x7ffff7750285 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007ffff762e47c in malloc_printerr (str=str#entry=0x7ffff7752690 "double free or corruption (!prev)") at malloc.c:5347
#4 0x00007ffff763012c in _int_free (av=0x7ffff7781b80 <main_arena>, p=0x5555569ff1e0, have_lock=<optimized out>) at malloc.c:4317
#5 0x00007ffff79518c4 in ?? () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#6 0x00007ffff795215a in ?? () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#7 0x00007ffff78ffd0e in ?? () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#8 0x00007ffff78fffa5 in ?? () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#9 0x00007ffff7900155 in ?? () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#10 0x00007ffff7903795 in ?? () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#11 0x00007ffff7905804 in mysql_real_query_nonblocking () from /lib/x86_64-linux-gnu/libmysqlclient.so.21
#12 0x0000555555559a4e in add_url (g=0x7ffff6e71e50) at threads.c:1202
#13 0x000055555555a69b in my_cb (loop=0x7ffff0000f70, w=0x7ffff6e71e58, revents=1) at threads.c:1457
#14 0x00007ffff7810bc3 in ev_invoke_pending () from /lib/x86_64-linux-gnu/libev.so.4
#15 0x00007ffff7814b93 in ev_run () from /lib/x86_64-linux-gnu/libev.so.4
#16 0x0000555555556a73 in ev_loop (loop=0x7ffff0000f70, flags=0) at /usr/include/ev.h:842
#17 0x000055555555a990 in crawler (threadid=0x0) at threads.c:1517
#18 0x00007ffff78b1609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#19 0x00007ffff76b8293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) q
As you can see the offending line is ev_loop(g.loop, 0); which causes the abort. I thought I was doing the right thing with making a new event loop in each thread with ev_loop_new.
What am I doing wrong?

Runtime check for LeakSanitizer (detect_leaks=1)

I have an issue where any Leak Sanitizer backtraces that go through dynamically loaded libraries report Unknown Module for any function calls within that library.
Direct leak of 48 byte(s) in 1 object(s) allocated from:
#0 0x4e3e36 in malloc (/usr/sbin/radiusd+0x4e3e36)
#1 0x7fb406e95f69 (<unknown module>)
#2 0x7fb406eafc36 (<unknown module>)
#3 0x7fb406eafd40 (<unknown module>)
#4 0x7fb406ea3364 (<unknown module>)
#5 0x7fb4063de7d4 (<unknown module>)
#6 0x7fb4063c61c4 (<unknown module>)
#7 0x7fb406617863 (<unknown module>)
#8 0x7fb415620681 in dl_load_func /usr/src/debug/freeradius-server-4.0.0/src/main/dl.c:194:34
#9 0x7fb41561edab in dl_symbol_init_walk /usr/src/debug/freeradius-server-4.0.0/src/main/dl.c:301:7
#10 0x7fb41561df1e in dl_module /usr/src/debug/freeradius-server-4.0.0/src/main/dl.c:748:6
#11 0x7fb41561f3db in dl_instance /usr/src/debug/freeradius-server-4.0.0/src/main/dl.c:853:20
#12 0x7fb41564f4ab in module_bootstrap /usr/src/debug/freeradius-server-4.0.0/src/main/module.c:827:6
#13 0x7fb41564ed56 in modules_bootstrap /usr/src/debug/freeradius-server-4.0.0/src/main/module.c:1070:14
#14 0x5352bb in main /usr/src/debug/freeradius-server-4.0.0/src/main/radiusd.c:561:6
#15 0x7fb41282ab34 in __libc_start_main (/lib64/libc.so.6+0x21b34)
#16 0x4204ab in _start (/usr/sbin/radiusd+0x4204ab)
I've had an almost identical issue with valgrind before, and I know it's due to the libraries being unloaded with dlclose on exit, and the symbols being unavailable when the symbolizer runs.
With valgrind the fix is simple
/*
* Only dlclose() handle if we're *NOT* running under valgrind
* as it unloads the symbols valgrind needs.
*/
if (!RUNNING_ON_VALGRIND) dlclose(module->handle); /* ignore any errors */
RUNNING_ON_VALGRIND being a macro provided by the valgrind library for detecting if the program is being valground.
I can't see anything in the LSAN docs for a similar feature for when ASAN_OPTIONS=detect_leaks=1 is set.
Does anyone know if it's possible to perform a runtime check for running under LSAN?
The LSAN interface headers allow the user to define a callback __lsan_is_turned_off to allow the program to disable the leak checker. This callback is only executed if LSAN is enabled.
#include <sanitizer/lsan_interface.h>
static bool running_under_lsan = false;
int __attribute__((used)) __lsan_is_turned_off(void)
{
running_under_lsan = true;
return 0;
}
EDIT: It's actually more complicated than that. As #yugr commented It appears __lsan_is_turned_off is only executed when a process or child process exits.
There is however a solution!
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sanitizer/common_interface_defs.h>
static int from_child[2] = {-1, -1};
static int pid;
int __attribute__((used)) __lsan_is_turned_off(void)
{
uint8_t ret = 1;
/* Parent */
if (pid != 0) return 0;
/* Child */
if (write(from_child[1], &ret, sizeof(ret)) < 0) {
fprintf(stderr, "Writing LSAN status failed: %s", strerror(errno));
}
close(from_child[1]);
return 0;
}
int main(int argc, char **argv)
{
uint8_t ret = 0;
if (pipe(from_child) < 0) {
fprintf(stderr, "Failed opening internal pipe: %s", strerror(errno));
exit(EXIT_FAILURE);
}
pid = fork();
if (pid == -1) {
fprintf(stderr, "Error forking: %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Child */
if (pid == 0) {
close(from_child[0]); /* Close parent's side */
exit(EXIT_SUCCESS);
}
/* Parent */
close(from_child[1]); /* Close child's side */
while ((read(from_child[0], &ret, sizeof(ret)) < 0) && (errno == EINTR));
close(from_child[0]); /* Close our side (so we don't leak FDs) */
/* Collect child */
waitpid(pid, NULL, 0);
if (ret) {
printf("Running under LSAN\n");
} else {
printf("Not running under LSAN\n");
}
exit(EXIT_SUCCESS);
}
Example:
clang -g3 -fsanitize=address foo.c
ASAN_OPTIONS='detect_leaks=1' ./a.out
Running under LSAN
ASAN_OPTIONS='detect_leaks=0' ./a.out
Not running under LSAN
First of all, not printing stacktraces on dlclose (or printing incorrect ones) is a known issue in all sanitizers (not just LSan).
Secondly, as of now there's no API to detect that LeakSanitizer is enabled at runtime so your best bet is to manually check that program is linked against Lsan and detect_leaks=0 isn't set in environment:
void (*__lsan_is_turned_off)() = dlsym(RTLD_DEFAULT, "__lsan_is_turned_off");
const char *lsan_opts = getenv("LSAN_OPTIONS");
const char *asan_opts = getenv("ASAN_OPTIONS");
int disable_dlclose = __lsan_is_turned_off != 0 && !__lsan_is_turned_off()
&& !(lsan_opts && (strstr(lsan_opts, "detect_leaks=0") || strstr(lsan_opts, "detect_leaks=false"))
&& !(asan_opts && (strstr(asan_opts, "detect_leaks=0") || strstr(asan_opts, "detect_leaks=false"));
(__lsan_is_turned_off is defined in sanitizer/lsan_interface.h).
If you enable LSan via -fsanitize=address, you can replace __lsan_is_turned_off check with #ifdef __SANITIZE_ADDRESS__.

double free or corruption (!prev) pthread

I'm having issues while implementing a multithread program.
The program seems to work fine for a single thread (when I set THREADS to 1) but for NTHREADS > 1, I'm getting the following error:
Segmentation fault (core dumped)
or
double free or corruption (!prev)
or
free(): invalid size: 0xb6b00a10 ***
0Aborted (core dumped)
as you can see the error varies a lot and I'm getting confused.
The program I'm executing is the following:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#define NTHREADS 5
typedef struct data_t
{
int num;
FILE *fp;
pthread_mutex_t mutex;
int thread_id;
}data_t;
void writefp(int num1, FILE *fp){
if(fp!=NULL){
int i;
int nume = 1;
int long_var=log10(nume);
for(i=long_var;i>=0;i--){
nume=(num1 / (int) round(pow(10, i)) % 10);
char d=nume+'0';
fwrite(&d, 1, 1, fp);
printf("%c", d);
}
}
fclose(fp);
}
void *thread_writefp(void* args)
{
data_t *data = (data_t *)args;
printf(" Thread id %d\n", data->thread_id);
pthread_mutex_lock(&(data->mutex));
writefp(data->num, data->fp);
pthread_mutex_unlock(&(data->mutex));
pthread_exit(NULL);
}
int randomf(){
int num,i;
for(i = 0; i<2; i++) {
num = rand()%100000+1;
}
return num;
}
int prime(int num1){
int is_prime=1;
int i = 2;
printf("Number: ");
while( i<=num1/2 && is_prime==1 ) {
printf("%i ", i);
if(i%30==0){
printf("\n");
}
if( num1 % i == 0 ) {
is_prime = 0;
}
i++;
}
printf("\n");
if(is_prime){
printf("%i is number prime\n", num1);
}else{
printf("NO is prime %i\n",num1);
}
return 0;
}
int main(void){
int i;
//int num1=randomf();
srand(time(NULL));
FILE *fp = fopen("fich.txt", "w+b");
data_t data;
pthread_t consumers_thread[NTHREADS];
data.mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
data.fp = fp;
//writefp( num1, fp);
for(i = 0; i < NTHREADS; i++)
{
data.num = randomf();
data.thread_id = i;
printf("Number prime is %i\n", prime(data.num));
if(pthread_create(&consumers_thread[i], NULL,
thread_writefp, (void*) &data) != 0)
{
fprintf(stderr, "%s\n", "Error creating thread!");
return EXIT_FAILURE;
}
}
// wait for all consumers thread to finish
for(i = 0; i < NTHREADS; ++i)
{
pthread_join(consumers_thread[i], NULL);
}
return EXIT_SUCCESS;
}
I compile the program as follows :
$gcc -pthread -Wall -o consummer consummer.c -lm
Here are for exemple tree error I got when I ran it with gdb tree successive time without changing anything to the code:
1
Thread 2 "consummer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7cc1b40 (LWP 18122)]
tcache_thread_freeres () at malloc.c:3003
3003 malloc.c: No such file or directory.
(gdb) bt
#0 tcache_thread_freeres () at malloc.c:3003
#1 0xb7e258c2 in __libc_thread_freeres () at thread-freeres.c:29
#2 0xb7ea03ad in start_thread (arg=0xb7cc1b40) at pthread_create.c:478
#3 0xb7dbb0a6 in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:108
(gdb)
2
Thread 3 "consummer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb72ffb40 (LWP 18131)]
0xb7d2af2b in __GI__IO_fwrite (buf=0xb72ff30f, size=1, count=1, fp=0x404160) at iofwrite.c:37
37 iofwrite.c: No such file or directory.
(gdb) run
3
Thread 3 "consummer" received signal SIGABRT, Aborted.
[Switching to Thread 0xb74c0b40 (LWP 18143)]
0xb7fd7cf9 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fd7cf9 in __kernel_vsyscall ()
#1 0xb7cf17e2 in __libc_signal_restore_set (set=0xb74bfe9c) at ../sysdeps/unix/sysv/linux/nptl-signals.h:80
#2 __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3 0xb7cf2f51 in __GI_abort () at abort.c:90
#4 0xb7d340cc in __libc_message (action=(do_abort | do_backtrace), fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:181
#5 0xb7d3af5d in malloc_printerr (action=<optimized out>, str=0xb7e418d8 "double free or corruption (!prev)", ptr=<optimized out>,
ar_ptr=0xb7e967a0 <main_arena>) at malloc.c:5425
#6 0xb7d3bb3b in _int_free (av=0xb7e967a0 <main_arena>, p=<optimized out>, have_lock=have_lock#entry=0) at malloc.c:4174
#7 0xb7d3fcb0 in __GI___libc_free (mem=0x404160) at malloc.c:3144
#8 0xb7e2587d in tcache_thread_freeres () at malloc.c:3004
#9 0xb7e258c2 in __libc_thread_freeres () at thread-freeres.c:29
#10 0xb7ea03ad in start_thread (arg=0xb74c0b40) at pthread_create.c:478
#11 0xb7dbb0a6 in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:108
(gdb)
I'd like/apreciate your help to know what I did wrong please. Thanks in advance.
Per this answer (but see Edit 2), multiple threads cannot safely access the same FILE *fp. As #IlyaBursov pointed out, you only have one data_t data shared across all threads — and, therefore, only one FILE * data.fp.
Thanks for your comment noting that you moved the fopen into the thread function. That way each thread independently opens and closes the file, so there is no FILE * sharing between threads.
This seems to be implementation-dependent — I was not able to reproduce the issue on Cygwin x64 with gcc 6.4.0. I suspect the effect of the mutex may also vary by implementation. It may also be dependent on compiler options — see this example.
Edit As #MichaelDorgan pointed out, calling fclose on a FILE * that other threads are using is also a bad idea.
Edit 2 As #JohnBollinger points out, individual stream operations are thread-safe these days. That would suggest that the fclose before another thread tried to access the file might be the problem. However, I wonder if perhaps the OP's stdio implementation is non-conformant in some way. I would think a compliant fwrite would simply return error on an access to a closed file, rather than crashing. See further comments below.

Sqlite3_bind_text segmentation fault

My app does a recursive scan of a given directory, I store each unique path in a database.
At one point I get a segfault and glibc fires:
*** glibc detected *** ./test: double free or corruption (!prev): 0x08cd1a20 ***
gdb confirms it.
The problem occurs when calling the function below:
int
populatePathDB(sqlite3* db, char *absolutePath)
{
char *sql;
sqlite3_stmt *stmt ;
int ret;
sql = "INSERT INTO paths (path) VALUES (?)";
ret = sqlite3_prepare_v2(db,sql,-1,&stmt,NULL);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
ret = sqlite3_bind_text(stmt, 1, absolutePath, -1, SQLITE_STATIC);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
sqlite3_step(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
/* sqlite3_clear_bindings(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
sqlite3_reset(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db)); */
ret = sqlite3_finalize( stmt );
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
return SQLITE_OK;
}
I guess the variable absolutePath (allocated by the caller) is deleted twice. Even Using SQLITE_TRANSIENT i've got the same fault.
Any ideas?
Adding recursive scan function:
int walkDir( char *dir, unsigned int recursive)
{
DIR* dirstream;
struct stat statbuf;
struct dirent *entry = NULL;
int exists, fd;
size_t dlen, entlen, nlen;
size_t buflen = 0;
char *baseName = NULL;
extern sqlite3 *magicDB_g;
extern sqlite3 *pathDB_g;
assert (dir !=NULL);
if ( ( dirstream = opendir(dir) ) == NULL ) {
ERR_MSG("opendir");
return (EXIT_FAILURE);
}
dlen = strlen(dir);
buflen = MEMCHUNK;
if (dlen >= buflen)
buflen = roundToNextPowerOf2(dlen);
baseName = xmalloc(buflen);
while ( ( entry = readdir(dirstream) ) ) {
if(!strcmp(".",entry->d_name) ||
! strcmp("..",entry->d_name))
continue;
if (entry->d_name[0] == '.')
continue;
nlen = dlen + (entlen = strlen(entry->d_name));
if (unlikely(nlen + 2 > buflen) )
xrealloc(baseName, buflen << 1);
if (dlen == 1 && *dir == '/' )
sprintf(baseName, "%s%s" , dir, entry->d_name);
else
sprintf(baseName, "%s/%s" , dir, entry->d_name);
/*snprintf (baseName, need + 2,"%s/%s", baseName, entry->d_name);*/
exists = lstat(baseName, &statbuf);
if (exists < 0)
continue;
if ( S_ISREG(statbuf.st_mode) && statbuf.st_size != 0 )
{
if ((fd = open(baseName, O_RDONLY)) == -1) {
ERR_MSG("open");
continue;
}
//fileSignature_v1(fd,NBYTES,magicDB_g);
if ( close(fd) == -1)
ERR_MSG("close");
}
if ( S_ISDIR(statbuf.st_mode) )
{
/* Create a absolute path database with unique entries */
populatePathDB(pathDB_g, baseName); <-- No segfault if not called.
if (recursive) {
printf("basename: %s\n",baseName);
walkDir(baseName,recursive);
}
}
}
free(baseName); <-- Seems to be deleted twice when back from populatePathDB()
if (closedir(dirstream) == -1)
ERR_MSG("closedir");
return (EXIT_SUCCESS);
}
Here's the error statement:
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x379440, bytes=34) at malloc.c:3598
3598 malloc.c: Aucun fichier ou dossier de ce type.
(gdb) bt
#0 _int_malloc (av=0x379440, bytes=34) at malloc.c:3598
#1 0x0024fd3c in __GI___libc_malloc (bytes=34) at malloc.c:2924
#2 0x0011541f in local_strdup (s=0xb7fe2a8c "/lib/i386-linux-gnu/libgcc_s.so.1") at dl-load.c:162
#3 0x001185d4 in _dl_map_object (loader=<optimized out>, name=<optimized out>, type=2, trace_mode=0, mode=-1879048191, nsid=0) at dl-load.c:2473
#4 0x00122d5d in dl_open_worker (a=0xbfffe690) at dl-open.c:225
#5 0x0011ecbf in _dl_catch_error (objname=0xbfffe6b4, errstring=0xbfffe6b8, mallocedp=0xbfffe6bf, operate=0x122c30 <dl_open_worker>, args=0xbfffe690)
at dl-error.c:178
#6 0x001227e4 in _dl_open (file=0x334345 "libgcc_s.so.1", mode=-2147483647, caller_dlopen=0x2d7e38, nsid=-2, argc=2, argv=0xbffff314, env=0x8051040)
at dl-open.c:639
#7 0x002fbd41 in do_dlopen (ptr=0xbfffe840) at dl-libc.c:89
#8 0x0011ecbf in _dl_catch_error (objname=0xbfffe814, errstring=0xbfffe818, mallocedp=0xbfffe81f, operate=0x2fbce0 <do_dlopen>, args=0xbfffe840)
at dl-error.c:178
#9 0x002fbe37 in dlerror_run (operate=<optimized out>, args=<optimized out>) at dl-libc.c:48
#10 0x002fbec7 in __GI___libc_dlopen_mode (name=0x334345 "libgcc_s.so.1", mode=-2147483647) at dl-libc.c:165
#11 0x002d7e38 in init () at ../sysdeps/i386/backtrace.c:44
#12 0x00388e8e in pthread_once () at ../nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S:122
#13 0x002d80a5 in __GI___backtrace (array=0xbfffee90, size=64) at ../sysdeps/i386/backtrace.c:121
#14 0x00241310 in __libc_message (do_abort=2, fmt=0x3393bc "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:180
#15 0x0024be42 in malloc_printerr (action=<optimized out>, str=<optimized out>, ptr=0x80c4eb8) at malloc.c:5007
#16 0x0804aa8f in walkDir (dir=0x8075a60 "/home/olivier/Téléchargements", recursive=1) at dirtraverser.c:251
#17 0x0804aa63 in walkDir (dir=0x80528f8 "/home/olivier", recursive=1) at dirtraverser.c:245
#18 0x0804bdc0 in main (argc=2, argv=0xbffff314) at main.c:246
Your xrealloc call (xrealloc(baseName, buflen << 1);) is wrong: you aren't assigning its result to baseName. xrealloc may free the buffer you give it (and return a different pointer), so if you don't assign the result then you may double-free the buffer.

Resources