C捕获strcat缓冲区溢出

此子程序需要三个用户输入:文本字符串,文件路径和1位标志。它将文件加载到缓冲区中,然后按该顺序将标志和文件缓冲区附加到充当有效负载的char数组中。它返回有效负载和原始用户字符串。

我收到一个错误,其中我在文件缓冲区,标志和有效负载上执行的某些字符串操作似乎破坏了user_string所在的内存。我通过将strcat(flag,buffer)交换为{{1}来修复了该错误。 }(这是我本来打算写的),但对于导致此错误的原因,我仍然感到困惑。

通过阅读文档(https://www.gnu.org/software/libc/manual/html_node/Concatenating-Strings.htmlhttps://www.gnu.org/software/libc/manual/html_node/Concatenating-Strings.html),我的猜测是strcpy(payload,flag) 扩展了 strcat字符串to个字节到未受保护的内存中,该文件内容将加载到缓冲区中的文件内容复制到缓冲区溢出中。

我的问题是:

  1. 我的猜测正确吗?

  2. 是否有办法可靠地防止这种情况发生?用strlen(to)检查来捕获这种东西是不可靠的,因为它不会始终返回明显错误的东西。您需要一个长度为if(){}的字符串,并得到一个filelength+1的字符串。

  3. 奖金/无关:调用变量而不进行任何运算是否会产生计算成本/缺点/影响?

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,SEEK_END); filelength = ftell(file); fseek(file,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 */ 4出现段错误,而不是返回“ lo World”。该行为在其他方面是等效的。

iCMS 回答:C捕获strcat缓冲区溢出

strcat完全按照文档所述:

char *strcat(char *restrict s1,const char *restrict s2); strcat()函数应附加s2指向的字符串的副本 (包括终止的空字节)到指向的字符串的末尾 到s1s2的初始字节将覆盖结尾的空字节 s1中的。如果在重叠的对象之间进行复制,则 行为是不确定的。

s1必须分配足够的内存以容纳两个字符串以及结尾的 nul

链接的文章是关于编程自己的字符串连接函数的。如何编写这样的函数取决于具体的应用程序-在此处说明。有很多方法。

在您的程序中,目标字符数组 不够大 ,结果是未定义的行为,甚至还不够大只能容纳一个字符串。

我强烈建议您学习一些C strings基础知识。

如果您想要更安全的strcat,可以编写自己的strcat,例如:

char *mystrcat(const char *str1,const char *str2)
{
    char *dest = NULL;
    size_t str1_length,str2_length;

    if(str1 && str2)
    {
        dest = malloc((str1_length = strlen(str1)) + (str2_length = strlen(str2)) + 1);
        if(dest)
        {
            memcpy(dest,str1,str1_length);
            memcpy(dest + str1_length,str2,str2_length);
        }
    }
    return dest;
}

但是为了安全起见,我们总是要付出代价-代码更长且效率更低。 C语言旨在尽可能高效地牺牲安全性,并在未定义行为的情况下引入这种想法。

,

您不能在1个字符的数组中存储非空字符串。字符串需要足够的空间容纳字符串内容和空终止符。

所以当你声明

char flag[1] = "1";

您仅分配了一个字节,其中包含字符1。没有空终止符。

将其与任何字符串函数一起使用将导致未定义的行为,因为它们会寻找空终止符来查找字符串的结尾。

strcat(flag,buffer)将搜索将在数组之外的空终止符,然后在其后附加buffer。因此,这显然会导致写入时缓冲区溢出。

strcpy(payload,flag)也是错误的。它将在flag个字节之后寻找一个空终止符,以知道何时停止复制到payload,因此它将复制的内容不只是flag(除非在此之后碰巧有一个空字节)它)。

您可以通过增加大小来解决strcpy()问题:

char flag[2] = "1";

您也可以将大小保留为空,编译器将使其足够大以容纳初始化它的字符串,包括空字节:

char flag[] = "1";
,

引起问题的行是因为strcat()试图将缓冲区塞进只有一个字符长的标志,并且您没有分配更多空间来容纳缓冲区。

如果要将缓冲区放入标志中,建议使用realloc()增加标志的长度以包括缓冲区的长度。

您唯一打印过的就是user_string。我不确定您是否要打印正在使用的其他字符串。

本文链接:https://www.f2er.com/2144018.html

大家都在问