execv()系统调用创建堆栈粉碎错误

时间:2018-03-18 02:32:11

标签: c stack-smash

每当我在我的代码中使用execv()时,它都可以工作并且没有错误,但仍会导致堆栈粉碎在运行时崩溃程序。我在这里做错了吗? 这是execv()的函数:

void execute(char *args[], char *cmd[])
{
    pid_t pid;
    int status;
    char bin[10] = "/bin/";
    pid = fork();

    // child process
    if(pid == 0)
    {
         strcat(bin, cmd[0]);

    execv(bin, args);   
    } else{
   perror("error");
    while(wait(&status) != pid);
    }
}

这里是我从中获取args和cmd的地方。它可能是我在这里做的事情引起的吗?

void parseString(char *command)
{
    char **args = malloc(sizeof(char*) * 16);
    int i = 0;
    int j = 0;
    char *cmd[1];

    // split each command by semicolons if necessary, then send each sub        command to parseString()
    if(strchr(command, ';')) {
        char *semi_token = strtok(command, ";");
        while(semi_token != NULL){
            args[i] = semi_token;
            semi_token = strtok(NULL, " ");
            parseString(args[i]);
            i++;
        }
    } else {
        // if no semi colons, split the commandby spaces and call execute() using the args and cmd
        char *token = strtok(command, " ");
        while(token != NULL)
        {
            args[i] = token;
            args[++i] = NULL;
            while(j == 0 && token != NULL) {
                    cmd[0] = token;
                    cmd[1] = NULL;
                    j++;
                }
            token = strtok(NULL, " ");
            }
            execute(args, cmd);
        }

        j = 0;
        i = 0;
        free(args);
    }

函数调用发生在这里。命令是从用户的stdin输入的。只需要位于/ bin /中的基本命令。类似于ls -l或cat文件。

while(1){
        command = getCommand();
        parseString(command);
}

1 个答案:

答案 0 :(得分:4)

你有两个严重的错误:一个会导致数组的越界写入,另一个可能会导致错误。

第一个,特定的越界写作,在parseString函数中。首先,您要声明cmd变量:

char *cmd[1];

这将cmd定义为 一个 元素的数组。然后你做

cmd[0] = token;
cmd[1] = NULL;

写入单元素数组的 两个 元素。写出越界导致undefined behavior

第二个错误发生在execute函数中,是我在第一条评论中谈到的错误。你有

char bin[10] = "/bin/";

bin定义为十个字符的数组,并填写其中的六个字符(不要忘记字符串终结符)。在孩子过程中,你做

strcat(bin, cmd[0]);

cmd[0]中的字符串附加到bin中的字符串。这里的问题是bin只有十个字符的空间,其中六个已经被使用(如上所述)。这意味着只留下四个字符的空间。如果命令超过了该命令,您也将超出范围并再次具有未定义的行为

第一个错误的解决方案很简单,让cmd成为两个元素的数组。第二个错误的解决方案是使bin更大,而不是连接超出数组的范围;或者动态分配数组(不要忘记终结符的空间)。

您的代码还存在许多其他潜在问题,例如args的16个指针的限制。而且你并没有真正解析parseString函数中的参数,每个参数都被视为一个单独的命令。并且在存在泄漏的情况下存在以分号分隔的"命令"。或者您不需要检查或处理所有需要的错误。即使没有错误,也可以使用errno