【发布时间】:2020-10-02 17:29:57
【问题描述】:
这个子程序接受三个用户输入:一个文本字符串、一个文件路径和一个 1 位标志。它将文件加载到缓冲区中,然后按顺序将标志和文件缓冲区附加到用作有效负载的 char 数组中。它返回有效负载和原始用户字符串。
我收到一个错误,其中我对文件缓冲区、标志和有效负载的某些字符串操作似乎损坏了 user_string 所在的内存。我通过将 strcat(flag, buffer) 交换为 strcpy(payload, flag) 来修复错误,(是我最初打算写的),但我仍然对导致此错误的原因感到困惑。
我从阅读文档(https://www.gnu.org/software/libc/manual/html_node/Concatenating-Strings.html,https://www.gnu.org/software/libc/manual/html_node/Concatenating-Strings.html)的猜测是 strcat 扩展 to 字符串 strlen(to) 字节到不受保护的内存,文件内容加载到在缓冲区溢出中复制的缓冲区。
我的问题是:
我的猜测正确吗?
有没有办法可靠地防止这种情况发生?用
if(){}检查来捕捉这类事情有点不可靠,因为它不会始终返回明显错误的东西;你期望一个长度为filelength+1的字符串并得到一个filelength+1的字符串。奖励/无关:调用变量而不对其进行操作是否有任何计算成本/缺点/影响?
/*
user inputs:
argv[0] = tendigitaa/four
argv[1] = ~/Desktop/helloworld.txt
argv[2] = 1
helloworld.txt is a text file containing (no quotes) : "Hello World"
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
int main (int argc, char **argv) {
char user_string[100] = "0";
char file_path[100] = "0";
char flag[1] = "0";
strcpy(user_string, argv[1]);
strcpy(file_path, argv[2]);
strcpy(flag, argv[3]);
/*
at this point printfs of the three declared variables return the same as the user inputs.
======
======
a bunch of other stuff happens...
======
======
and then this point printfs of the three declared variables return the same as the user inputs.
*/
FILE *file;
char * buffer = 0;
long filelength;
file = fopen(file_path, "r");
if (file) {
fseek(file, 0, SEEK_END);
filelength = ftell(file);
fseek(file, 0, SEEK_SET);
buffer = malloc(filelength);
printf("stringcheck1: %s \n", user_string);
if (buffer) {
fread(buffer, 1, filelength, file);
}
}
long payloadlen = filelength + 1;
char payload[payloadlen];
printf("stringcheck2: %s \n", user_string);
strcpy(payload, flag);
printf("stringcheck3: %s \n", user_string);
strcat(flag, buffer);
printf("stringcheck4: %s \n", user_string); //bug here
free(buffer);
printf("stringcheck5: %s \n", user_string);
payload; user_string; //bonus question: does this line have any effect on the program or computational cost?
return 0;
}
/*
printf output:
stringcheck1: tendigitaa/four
stringcheck2: tendigitaa/four
stringcheck3: tendigitaa/four
stringcheck4: lo World
stringcheck5: lo World
*/
注意:将此部分从主程序中取出会导致stringcheck 4 出现段错误,而不是返回“lo World”。该行为在其他方面是等效的。
【问题讨论】:
-
你的编译器对奖金问题有什么看法?答案:警告:声明无效。
-
什么是不受保护的内存以及它与 strcat 问题的关系?
标签: c string buffer strcpy strcat