getline как ограничить количество вводимых данных с помощью fgets - PullRequest
0 голосов
/ 21 января 2019

Руководство по GNU

Эта цитата взята из руководства по GNU

Предупреждение: если входные данные имеют нулевой символ, вы не можете сказать.Так что не используйте fgets, если вы не знаете, что данные не могут содержать ноль.Не используйте его для чтения файлов, отредактированных пользователем, потому что, если пользователь вставляет нулевой символ, вы должны либо обработать его правильно, либо распечатать четкое сообщение об ошибке.Мы рекомендуем использовать getline вместо fgets.

Как обычно, я потратил время на поиск, прежде чем задавать вопрос, и нашел такой же вопрос о переполнении стека пять лет назад: Почемуфункция fgets устарела?

Хотя GNU рекомендует getline вместо fgets, я заметил, что getline в stdio.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 будет malloc и realloc для меня по мере необходимости.

#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.Я думаю, что злоумышленник может использовать цикл для отправки неограниченного объема данных и использовать все оперативные памяти, доступные в куче?

Есть ли способ ограничения размера ввода, который используется getline или getline имеет некоторое ограничение в функции?

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Руководство по GNU просто плохое.Ограничение длины ввода обычно правильно, особенно если ввод ненадежен, и fgets делает это правильно.getline не может безопасно использоваться в таком контексте.

0 голосов
/ 21 января 2019

Использование fgets не обязательно проблематично, все, что вам скажет руководство gnu, заключается в том, что если в файле есть байт '\ 0', то и он будет в вашем буфере.Вы не сможете определить, является ли нулевой разделитель в вашем буфере фактическим концом файла или просто нулевым в файле.Это означает, что вы можете прочитать 100-символьный файл в 200-символьный буфер, и он будет содержать 50-символьную строку c.

На самом деле readline stdio.h, похоже, не имеет каких-либо нормальных ограничений длины, так что freadможет быть жизнеспособной альтернативой.

Unlinke C getline и C ++ std::getline(), C ++ std::istream::getline() ограничен countсимволы

...