首页 > 解决方案 > getline 如何像使用 fgets 一样限制输入量

问题描述

GNU 手册

此引用来自 GNU 手册

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

像往常一样,我在提问之前花时间搜索,我确实在五年前的 Stack Overflow 上发现了一个类似的问题: 为什么不推荐使用 fgets 函数?

尽管 GNU 建议使用getlineover fgets,但我注意到getlineinstdio.h采用任何大小的行。它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中的安全编码实践

我正在考虑从 切换fgetsgetline,但我遇到的问题是我无法弄清楚如何限制getline. 我认为恶意攻击者可以使用循环发送无限量的数据,并用尽堆中所有可用的内存?

getline有没有办法限制在函数中使用或确实有一些限制的输入大小getline

标签: csecurityfgetsgetline

解决方案


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

stdio.h readline 实际上似乎没有任何合理的长度限制,因此 fread 可能是可行的替代方案。

Unlinke C getlineand C++ std::getline(), C++std::istream::getline()仅限于count字符


推荐阅读