使用strcpy和strcat时堆栈粉碎

时间:2021-10-14 04:31:11

I've been trying to debug this for a while, still can't figure out why this causes a stack smashing error (I think the error code is 6, or abort. Essentially this function takes a directory, opens a file and then puts that file into a function so it can use the file, and then outputs the number of times it goes through the function.

我一直试图调试这一段时间,仍然无法弄清楚为什么这会导致堆栈粉碎错误(我认为错误代码是6,或者是中止。本质上这个函数占用一个目录,打开一个文件然后放入该文件放入一个函数,以便它可以使用该文件,然后输出它通过该函数的次数。

int map(char* dir, void* results, size_t size, int (*act)(FILE* f, void* res, char* fn))
 {
      printf("%s\n", dir);
      char copyDirectory[strlen(dir)+1];
      //adds the slash
      strcpy(copyDirectory, dir);
      strcat(copyDirectory, "/");
      //before the psuedocode, get all the files in the directory
      int numFiles = nfiles(copyDirectory);
      DIR* directory = opendir(copyDirectory);
      //if there aren't any files, then we exit
      if(numFiles == 0)
      {
           closedir(directory);
           return -1;
      }
      //reads the file from the directory
      struct dirent* readFile = readdir(directory);
      int output = 0;
      while(readFile!=NULL)
      {
           if(readFile->d_type==DT_REG)
           {
               //step 2: obtain filepath
               char* fileName = readFile->d_name;
               int filePathLength = strlen(dir) + strlen(fileName) + 1;//add one for the slash
               char filePath[filePathLength];
               memset(filePath, 0, filePathLength); //allocat ememory for file path
               strcpy(filePath, strcat(dir, fileName));
               //step 3: open file
               FILE* file = fopen(filePath, "r");
               //if the file is unreachable, exit
               if(file==NULL)
               {
                    closedir(directory);
                    return -1;
               }
               //step 4: perform some action and store result
               strcpy(dir, copyDirectory);
               act(file, results, fileName);
               //step 5: close file
               fclose(file);
               //to go through loop: increment the readFile
                    ++output;
                }
                readFile = readdir(directory);
      }
      closedir(directory);
      return output;
 }

Map function with the example.

使用示例映射函数。

int map(char* dir, void* results, size_t size, int (*act)(FILE* f, void* res, char* fn))
{
     char* copyDirectory = strdup(dir);
     DIR* directory = opendir(dir);
     int output = 0;
     struct dirent* readFile = readdir(directory);
     while(readFile!=NULL)
     {
         if(readFile->d_type==DT_REG)
         {
             //step 2: obtain filepath
             char* fileName = readFile->d_name;
             int filePathLength = strlen(dir) + strlen(fileName) +2;//add one for the slash
             char filePath[filePathLength+1];
             memset(filePath, 0, filePathLength); //allocat ememory for file path
             strcpy(filePath, strcat(dir, fileName));
             //step 3: open file
             FILE* file = fopen(filePath, "r");
             //if the file is unreachable, exit
             if(file==NULL)
             {
                 closedir(directory);
                 return -1;
             }
             //step 4: perform some action and store result
             strcpy(dir, copyDirectory);
             act(file, results, fileName);
             //step 5: close file
             fclose(file);
             //to go through loop: increment the readFile
             ++output;
         }
         readFile = readdir(directory);
     }  
     closedir(directory);
     return output;
}
//Sample Map function action: Print file contents to stdout and returns the number bytes in the file.
int cat(FILE* f, void* res, char* filename) {
    char c;
    int n = 0;
    printf("%s\n", filename);
    while((c = fgetc(f)) != EOF) {
        printf("%c", c);
        n++;
    }
    printf("\n");
    return n;
}
int main(int argc, char const *argv[])
{
    char directory[]= "../rsrc/ana_light/";
    size_t size = 100;
    void* results[500]; 
    int mapCat = map(directory, results, size, cat);
    printf("The value of map is %d.\n", mapCat);
    return EXIT_SUCCESS;
}

Where this fails is after it has executed and it prints to the output. The function should print out the contents of the files you have. The directory list needs to have a "/" at the end. Currently it prints the file contents and exits with the value of how many files it read, but it drops off after it exits with the stack smashing error.

失败的地方是它执行完毕并打印到输出后。该函数应打印出您拥有的文件的内容。目录列表最后需要有一个“/”。目前它打印文件内容并以其读取的文件数值退出,但在退出时出现堆栈粉碎错误后会退出。

EDIT1: Edited the code to reflect the changes I've made.

EDIT1:编辑代码以反映我所做的更改。

EDIT2: Done according to the MCVE standards, I think? Should run if I'm not mistaken.

编辑2:根据MCVE标准完成,我想?如果我没弄错的话应该跑。

1 个解决方案

#1


2  

First problem: change

第一个问题:改变

    char copyDirectory[strlen(dir)+1];

to

    char copyDirectory[strlen(dir)+2];

Second problem: change

第二个问题:改变

       char filePath[filePathLength];

to

       char filePath[filePathLength+1];

Third problem (change appears to have not been there on first read):

第三个问题(第一次阅读时似乎没有变化):

     //strcpy(copyDirectory, dir);
     strcat(copyDirectory, dir);

The commented out code was correct:

注释掉的代码是正确的:

    strcpy(copyDirectory, dir);

You've been forgetting spaces for trailing null characters.

你一直在忘记尾随空字符的空格。

Fourth problem: You forgot to handle opendir failing.

第四个问题:你忘了处理opendir失败了。

Fifth problem: this code is wrong:

第五个问题:这段代码错了:

        memset(filePath, 0, filePathLength); //allocat ememory for file path
        strcpy(filePath, strcat(dir, fileName));

change to:

改成:

         strcpy(filePath, copyDirectory);
         strcat(filePath, fileName);

Don't write to your input variables here. This is a very bad idea.

不要在这里写入输入变量。这是一个非常糟糕的主意。

After undoing the (leaky) strdup for copyDirectory and putting your very innovative local buffer back I was able to get the code to run through to completion.

在撤消copyDirectory的(漏洞)strdup并将你非常创新的本地缓冲区恢复后,我能够让代码完成运行。

#1


2  

First problem: change

第一个问题:改变

    char copyDirectory[strlen(dir)+1];

to

    char copyDirectory[strlen(dir)+2];

Second problem: change

第二个问题:改变

       char filePath[filePathLength];

to

       char filePath[filePathLength+1];

Third problem (change appears to have not been there on first read):

第三个问题(第一次阅读时似乎没有变化):

     //strcpy(copyDirectory, dir);
     strcat(copyDirectory, dir);

The commented out code was correct:

注释掉的代码是正确的:

    strcpy(copyDirectory, dir);

You've been forgetting spaces for trailing null characters.

你一直在忘记尾随空字符的空格。

Fourth problem: You forgot to handle opendir failing.

第四个问题:你忘了处理opendir失败了。

Fifth problem: this code is wrong:

第五个问题:这段代码错了:

        memset(filePath, 0, filePathLength); //allocat ememory for file path
        strcpy(filePath, strcat(dir, fileName));

change to:

改成:

         strcpy(filePath, copyDirectory);
         strcat(filePath, fileName);

Don't write to your input variables here. This is a very bad idea.

不要在这里写入输入变量。这是一个非常糟糕的主意。

After undoing the (leaky) strdup for copyDirectory and putting your very innovative local buffer back I was able to get the code to run through to completion.

在撤消copyDirectory的(漏洞)strdup并将你非常创新的本地缓冲区恢复后,我能够让代码完成运行。