gets — функция, входящая в Стандартную библиотеку языка Си, объявляемая в заголовочном файле stdio.h, которая считывает строку стандартного ввода и помещает её в буфер, созданный вызывающей функцией. Если выдаёт ошибку, то теперь для её вызова следует использовать gets_s.

Реализация Может быть реализована следующим способом (при помощи getchar):

char *gets(char *s) { /*очистка буфера ввода */ fflush(stdin);

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 в новых программах — «Никогда не используйте gets(). Так как невозможно сказать, не зная ничего о данных, сколько символов будет прочитано gets(), и поэтому gets() продолжит помещать символы в буфер и после его заполнения, что весьма опасно в использовании. Это способно нарушить информационную защиту компьютерной системы.».

Применение 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, защитная страница может помочь с обработкой ошибок.

Примечания

Ссылки

Категория:Stdio.h Категория:Статьи с примерами кода Си Категория:Небезопасные функции Си