1
votes

I'm writing a snippet of code to check if a file exists. When the user passes in a file argument with just a name ( no slashes ) I am to check to see if the file exists using paths in the PATH environment variable. I'm on Ubuntu compiling with gcc and have been using gdb. I found the line which is causing the SIGABRT but am unsure of what the information is telling me. This is my first time using gdb. Here's my snippet:

char* PATH = NULL;
PATH = (char*)getenv( "PATH" );
char* pathtoken = strtok( PATH, ":" );
int index = 0;

while ( pathtoken != NULL )
{
    index++;
    printf( "%s\n", pathtoken );
    char* pathdir = (char*)malloc( sizeof(pathtoken) );
    strcpy( pathdir, pathtoken );
    GetFullPath( pathdir, filename );
    inputstream = fopen( pathdir, "r" );

    if ( inputstream != NULL)
    {
        free( pathdir );
        break;
        }

        free( pathdir );
        pathtoken = strtok( NULL, ":" );
    }

char* GetFullPath( char* dirpath, char* filename )
{
    //Append back slash
    int len = strlen(dirpath);
    dirpath[len] = '/';
    dirpath[len+1] = '\0';

    return strcat( dirpath, filename );
}

It happens on the first iteration at the fopen line. Here's my gdb output

Starting program: /home/seapoe/Documents/OsClass/CodePractice/a.out text1 /usr/lib/lightdm/lightdm

Breakpoint 1, main (argc=2, argv=0xbffff3a4) at xssh.c:87

87 GetFullPath( pathdir, filename );

(gdb) next

89 inputstream = fopen( pathdir, "r" );

(gdb) print pathdir

$5 = 0x804c008 "/usr/lib/lightdm/lightdm/text1"

(gdb) print pathdir[strlen(pathdir)]

$6 = 0 '\000'

(gdb) print pathdir[strlen(pathdir)+1]

$7 = 0 '\000'

(gdb) print pathdir[strlen(pathdir)+2]

$8 = 0 '\000'

(gdb) print pathdir[strlen(pathdir)-1]

$9 = 49 '1'

(gdb) next

* glibc detected /home/seapoe/Documents/OsClass/CodePractice/a.out: free(): invalid next size (normal): 0x0804c018 **

======= Backtrace: =========

/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb7e97ee2]

/lib/i386-linux-gnu/libc.so.6(+0x65db5)[0xb7e87db5]

/lib/i386-linux-gnu/libc.so.6(fopen+0x2b)[0xb7e87deb]

/home/seapoe/Documents/OsClass/CodePractice/a.out[0x8048a77]

/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb7e3b4d3]

/home/seapoe/Documents/OsClass/CodePractice/a.out[0x8048771]

======= Memory map: ========

08048000-0804a000 r-xp 00000000 08:01 536263 /home/seapoe/Documents/OsClass /CodePractice/a.out

0804a000-0804b000 r--p 00001000 08:01 536263 /home/seapoe/Documents/OsClass/CodePractice/a.out

0804b000-0804c000 rw-p 00002000 08:01 536263 /home/seapoe/Documents/OsClass/CodePractice/a.out

0804c000-0806d000 rw-p 00000000 00:00 0 [heap]

b7df3000-b7e0f000 r-xp 00000000 08:01 394136 /lib/i386-linux-gnu/libgcc_s.so.1

b7e0f000-b7e10000 r--p 0001b000 08:01 394136 /lib/i386-linux-gnu/libgcc_s.so.1

b7e10000-b7e11000 rw-p 0001c000 08:01 394136 /lib/i386-linux-gnu/libgcc_s.so.1

b7e21000-b7e22000 rw-p 00000000 00:00 0

b7e22000-b7fc5000 r-xp 00000000 08:01 394115 /lib/i386-linux-gnu/libc-2.15.so

b7fc5000-b7fc7000 r--p 001a3000 08:01 394115 /lib/i386-linux-gnu/libc-2.15.so

b7fc7000-b7fc8000 rw-p 001a5000 08:01 394115 /lib/i386-linux-gnu/libc-2.15.so

b7fc8000-b7fcb000 rw-p 00000000 00:00 0

b7fd9000-b7fdd000 rw-p 00000000 00:00 0

b7fdd000-b7fde000 r-xp 00000000 00:00 0 [vdso]

b7fde000-b7ffe000 r-xp 00000000 08:01 394095 /lib/i386-linux-gnu/ld-2.15.so

b7ffe000-b7fff000 r--p 0001f000 08:01 394095 /lib/i386-linux-gnu/ld-2.15.so

b7fff000-b8000000 rw-p 00020000 08:01 394095 /lib/i386-linux-gnu/ld-2.15.so

bffdf000-c0000000 rw-p 00000000 00:00 0 [stack]

Program received signal SIGABRT, Aborted.

0xb7fdd424 in __kernel_vsyscall ()

After calling GetFullPath you can see a valid path is returned before the fopen call

2

2 Answers

5
votes
char* pathdir = (char*)malloc( sizeof(pathtoken) );

is wrong. sizeof(pathtoken) will give you the size of the pointer on your system (4 or 8). You want

pathdir = strdup(pathtoken)

which is also wrong, given that you are trying to append to it. Just make pathdir a char array of MAX_PATH (or PATH_MAX depending on your OS) length.

2
votes

The problem is this:

sizeof(pathtoken)

The sizeof operator doesn't work that way, it's just giving you the size of a pointer variable, and isn't providing enough space. What you actually want is:

char* pathdir = malloc( strlen(pathtoken) + 1 );

or, as MK. states, this is what you'd want if you weren't trying to stuff even more characters in there during GetFullPath(). To compensate, either set up a big enough static array as he suggests, or do something like:

pathdir = GetFullPath( pathdir, filename );

....

char* GetFullPath( char* dirpath, char* filename )
{
    char * temp_path = malloc(strlen(dirpath) + strlen(filename) + 2);
    if ( temp_path == NULL ) {
        fprintf(stderr, "No memory!\n");
        exit(EXIT_FAILURE);
    }

    sprintf(temp_path, "%s/%s", dirpath, filename);
    free(dirpath);
    return temp_path;
}

Don't cast the return from malloc() in C.