Andre Fox Andre Fox - 6 months ago 59
C Question

Segfault on execvp using command line arguments

I am working on a programming assignment that ask me to write a code able to read a command from the command line, together with its argument, and execute the program using the execvp.
This is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, const char * argv[]) {

char **cmd;
int i;

if (argc == 1){

fprintf(stdout, "No command inserted!\n");
exit(EXIT_SUCCESS);

}

cmd = (char **) malloc( argc * sizeof(char *));
cmd[0] = strdup(argv[1]);

if (argc > 2){

for (i = 1 ; i < argc - 1 ; i++ ){

cmd[i] = (char *) malloc( strlen(argv[i+1]) * sizeof(char) );
strcpy(cmd[i], argv[i+1]);

}

cmd[argc] = NULL;
execvp(cmd[0], cmd);

fprintf(stderr, "Failed Execution or not existing command!!\n");
exit(EXIT_FAILURE);

}

cmd[1] = NULL;

execvp(cmd[0], cmd);

fprintf(stderr, "Failed Execution or not existing command!!\n");
exit(EXIT_FAILURE);

return 0;
}


The code works fine typing no arguments command such as:

./a.out who
./a.out ls


but result in a 'Segmentation Fault:11' when writing commands like:

./a.out ls -l
./a.out more file.txt


I can't figure out where is the problem...

Answer Source

There are at least two points where you exceed array bounds:

cmd[i] = (char *) malloc( strlen(argv[i+1]) * sizeof(char) )

is one off as it does not consider the terminating \0-character, such that a strcpy(cmd[i], argv[i+1]) then will exceed the bounds. Write ...

cmd[i] = (char *) malloc( (strlen(argv[i+1]) + 1) * sizeof(char) )

instead. BTW: sizeof(char) is always 1 by definition.

Further,

cmd = (char **) malloc( argc * sizeof(char *));
...
cmd[argc] = NULL;

is again one off. It should be cmd = (char **) malloc( (argc+1) * sizeof(char *)) when you like to assign cmd[argc] = NULL.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download