Предотвращение переполнения буфера с помощью
Объявление gets
:
char * gets ( char * str );
Обратите внимание на вопиющее упущение максимального размера для str.
cplusplus.com говорит 2
Обратите внимание, что получение отличается от fgets: не только использует stdin как источник, но он не включает символ окончания строки в полученной строке и не позволяет указать максимальный размер для str (, что может привести к переполнению буфера).
А также:
Самая последняя версия стандарта C (2011) окончательно удалил эту функцию из ее спецификации. Функция устаревший в С++ (по состоянию на 2011 год, который следует за C99 + TC3).
Теперь, конечно, fgets
обычно рекомендуется в качестве замены gets
, потому что его объявление выглядит следующим образом:
char * fgets ( char * str, int num, FILE * stream );
Он ДАЕТ принять параметр размера. Это делает его намного безопаснее, чем gets
.
Теперь, поскольку я не хочу тратить деньги на скачивание или покупку C11 standard
, может ли кто-нибудь пролить свет на причину обесценивания gets
и что это значит для будущего кода? Почему он существует в том же месте, когда fgets
безопаснее? И почему он только сейчас устарел?
Ответы
Ответ 1
gets
устарел, поскольку он небезопасен, как вы уже цитировали, это может вызвать переполнение буфера. Для замены C11 предоставляет альтернативу gets_s
с такой подписью:
char *gets_s(char *s, rsize_t n);
Обратите внимание, что C11 по-прежнему рекомендует fgets
заменить gets
.
В самом деле, ставит ли стандарт gets
в противоречие, но Комитет решил, что gets
полезен, когда программист имеет адекватный контроль над вводом.
Здесь официальное разъяснение Комитета.
Поскольку gets
не проверяет переполнение буфера, обычно его небезопасно использовать, когда его вход не находится под контролем программистов. Это заставило некоторых допросить, должно ли оно вообще появляться в Стандарте. Комитет решил, что gets
был полезен и удобен в тех особых обстоятельствах, когда программист действительно имеет адекватный контроль над исходными данными и как многолетняя существующая практика, ему нужна стандартная спецификация. В общем, однако, предпочтительная функция fgets
(см. П. 7.19.7.2).
Ответ 2
Теперь, поскольку я не хочу тратить деньги на скачивание или покупку стандарта C11, может ли кто-нибудь пролить свет на причину обескураживания и что это означает для будущего кода?
Из комитета C в C99 Обоснование:
Поскольку gets не проверяет переполнение буфера, обычно его небезопасно использовать, когда его вход не находится под контролем программистов. Это заставило некоторых допросить, должно ли оно вообще появляться в Стандарте. Комитет решил, что получение было полезным и удобным в тех особых обстоятельствах, когда у программиста есть достаточный контроль над исходными данными, и как многолетняя существующая практика, ему нужна стандартная спецификация. В целом, однако, предпочтительной функцией является fgets.