c-getline如何使用fgets限制输入量



GNU手册

这句话来自GNU手册

警告:如果输入数据有一个空字符,你无法判断。所以除非知道数据不能包含null,否则不要使用fgets。不要使用它来读取用户编辑的文件,因为如果用户插入null字符,您应该正确处理它或打印一个clear错误消息。我们建议使用getline而不是fgets。

正如我通常所做的那样,在提出问题之前,我花了一些时间进行搜索,并且我确实在五年前的Stack Overflow上发现了一个类似的问题:为什么不赞成使用fgets函数?

尽管GNU推荐getline而不是fgets,但我注意到stdio.h中的getline采用任何大小的行。它根据需要调用realloc。如果我尝试将大小设置为10个字符:

#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buffer;
size_t bufsize = 10;
size_t characters;
buffer = (char *)malloc(bufsize * sizeof(char));
if( buffer == NULL)
{
perror("Unable to allocate buffer");
exit(1);
}
printf("Type something: ");
characters = getline(&buffer,&bufsize,stdin);
printf("%zu characters were read.n",characters);
printf("You typed: '%s'n",buffer);
return(0);
}

在上面的代码中,键入超过10个字符的任意大小的字符串,getline将读取它并为您提供正确的输出。

甚至不需要malloc,就像我在上面的代码中所做的那样——getline为您做这件事。我将缓冲区设置为大小0,getline将根据需要为我设置mallocrealloc

#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buffer;
size_t bufsize = 0;
size_t characters;
printf("Type something: ");
characters = getline(&buffer,&bufsize,stdin);
printf("%zu characters were read.n",characters);
printf("You typed: '%s'n",buffer);
return(0);
}

如果你运行这个代码,你可以再次输入任何大小的字符串,它是有效的。尽管我将缓冲区大小设置为0。

我一直在研究CERT指南www.securecoding.CERT.org 中的安全编码实践

我想从fgets切换到getline,但我遇到的问题是,我不知道如何限制getline中的输入。我认为恶意攻击者可以使用循环发送无限量的数据,并耗尽堆中所有可用的ram?

是否有限制getline使用的输入大小的方法,或者getline在函数中是否有一些限制?

使用fgets不一定有问题,gnu手册告诉你的是,如果文件中有一个"\0"-字节,那么缓冲区中也会有。您将无法判断缓冲区中的null分隔符是文件的实际结尾,还是只是文件中的null。这意味着您可以将一个100个字符的文件读取到一个200个字符的缓冲区中,它将包含一个50个字符的c字符串。

事实上,stdio.h读出线似乎没有任何合理的长度限制,因此fread可能是一个可行的替代方案。

取消链接Cgetline和C++std::getline(),C++std::istream::getline()仅限于count字符

GNU手册太糟糕了。限制输入长度通常是正确的做法,尤其是在输入不可信的情况下,并且fgets正确地做到了这一点。CCD_ 21不能在这样的上下文中安全地使用。

最新更新