15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Защита от переполнения буфера

Переполнение буфера обычно происходит, когда программа пытается записать данные за пределы конца буфера. Рассмотрим пример:

#include <stdio.h>
int main()
{
  char buff[15] = {0};  /*все элементы инициализируются нулём*/
  printf("enter your name: ");
  scanf(buff, "%s"); /*опасно, так как длина не проверяется*/
}

Программа считывает строку со стандартного ввода (клавиатура). Проблема в том, что она не проверяет длину строки. Если будет введено более 14 символов, то произойдёт переполнение буфера, так как scanf() попытается сохранить остальные символы за пределами buff (не забудьте, что один символ всегда зарезервирован для нуля, которым должна заканчиваться строка). В результате обычно происходит аварийное завершение.

Но это ещё не самая страшная ситуация. Намного опаснее, если программа спокойно продолжит своё выполнение. Хотя специалисты, которые знакомы с внутренней организацией системы, могу спокойно встраивать в программный код специальные обработчики таких исключительных ситуаций, которые позволяют проверять правильность следующей интсрукции процессора и решать - продолжать выполнение кода либо пропустить его и вызвать другую подпрограмму, и т.д.

Однако, мы пойдём другим путём. Для начала всегда проверяйте границы массива перед записью его в буфер. Если это невозможно, например, когда ввод производится из скрипта CGI, то используйте функции, которые явно ограничивают количество вводимых сиволов, т.е. вместо scanf() используйте функцию fgets(), которая считывает символы до определённого предела:

#include <stdio.h>
int main()
{
 char buff[15] = {0};
 fgets(buff, sizeof(buff), stdin); /*считывает только 14 символов*/
}

Так же стандартные строковые функции имеют аналоги, которые позволяют ограничить размер. Таким образом, вместо strcpy (), strcmp (), и sprintf (), используют strncpy (), strncmp (), и snprint (), соответственно.