- gets
-
gets
— функция, входящая в Стандартную библиотеку языка Си, объявляемая в заголовочном файлеstdio.h
, которая считывает строку стандартного ввода и помещает ее в буфер, созданный вызывающей функцией.Содержание
Реализация
Может быть реализована следующим способом (при помощи
getchar
):char *gets(char *s) { int i, k = getchar(); /* Возвращаем NULL если ничего не введено */ if (k == EOF) return NULL; /* Считываем и копируем в буфер символы пока не достигнем конца строки или файла */ for (i = 0; k != EOF && k != '\n'; ++i) { s[i] = k; k = getchar(); /* При обнаружении ошибки результирующий буфер непригоден */ if (k == EOF && !feof(stdin)) return NULL; } /* Нуль-терминируем и возвращаем буфер в случае успеха. Символ перевода строки в буфере не хранится. */ s[i] = '\0'; return s; }
Программист должен знать максимум числа символов, которые должны быть считаны
gets
, чтобы удостовериться, что выделяется буфер достаточного размера. Подобное невозможно без информации о данных. Эта проблема может приводить к созданию ошибок и открывает простор для нарушений компьютерной безопасности при помощи переполнения буфера. Многие источники советуют программистам никогда не использоватьgets
в новых программах[1][2][3].Применение
gets
весьма осуждается. Функция оставлена в стандартах C89 и C99 для обратной совместимости. Множество инструментов разработки ПО, как например, GNU ld выдает предупреждения в случае обнаружения при компоновке кода с использованиемgets
.Альтернативы
Вместо
gets
могут быть использованы другие функции строкового ввода, что позволит избежать ошибок, связанных с переполнением буфера. Простейшим вариантом будетfgets
. При замене кода видаchar buffer[BUFFERSIZE]; gets(buffer);
кодом вида
char buffer[BUFFERSIZE]; fgets(buffer, sizeof(buffer), stdin);
нужно иметь в виду, что вызов
fgets(buffer, sizeof buffer, stdin)
отличается отgets(buffer)
не только защитой от переполнения буфера, но и тем, чтоfgets(buffer, sizeof buffer, stdin)
сохраняет завершающий символ перевода строки (если ввод линии заканчивается символом перевода строки), в то время какgets(buffer)
отбрасывает его.Безопасность использования
Безопасное использование
gets
требует от программиста проверки того, что переполнение буфера не станет проблемой. Стандарт языка Си этого не гарантирует; тем не менее, существует несколько относительно усложненных способов проверки этого с различной степенью переносимости. Одним из возможных вариантов является защитная страница для защиты памяти. Сам по себе этот метод переполнения буфера превращает в падения системы. В сочетании с обработчиками исключений, такими какSIGSEGV
иsigaction
, защитная страница может помочь с изящной обработкой ошибок.Примечания
- ↑ GNU GNU Библиотека Си — Строковый Ввод. — «Функция
gets
весьма опасна, так как она не обеспечивает никакой защиты от переполнения строкиs
. Библиотека GNU включает ее только ради совместимости. Вам следует всегда использовать вместо нееfgets
илиgetline
.» Архивировано из первоисточника 19 марта 2012. Проверено 2 августа 2008. - ↑ Почему все говорят не использовать
gets()
?. comp.lang.c Часто Задаваемые Вопросы. Архивировано из первоисточника 19 марта 2012. Проверено 2 августа 2008. - ↑
gets(3)
— страница справки man по библиотечным функциям GNU/Linux (англ.) — «Никогда не используйтеgets()
. Так как невозможно сказать, не зная ничего о данных, сколько символов будет прочитаноgets()
, и поэтомуgets()
продолжит помещать символы в буфер и после его заполнения, что весьма опасно в использовании. Это способно нарушить информационную защиту компьютерной системы.»
Ссылки
gets
— системные интерфейсы, The Single UNIX® Specification, выпуск 7 от The Open Group (англ.)
Категории:- Stdio.h
- Небезопасные функции Си
- ↑ GNU GNU Библиотека Си — Строковый Ввод. — «Функция
Wikimedia Foundation. 2010.