Secure C и университеты - обучены переполнению буфера - PullRequest
3 голосов
/ 27 января 2009

Я недавно закончил университетский курс в C. Поэтому, конечно, мне не хватает опыта.

Некоторые университеты, как правило, учат своих студентов безопасному программированию, или хотя бы некоторым элементам . Есть даже видео (взято из здесь ).

Находясь в C, копируя строки, мне нужны - насколько я знаю - функции strcpy или string.h. Как вы используете это безопасно в повседневном программировании? Есть ли у вас некоторые функции, которые обрабатывают распределение для предотвращения переполнения буфера? Для C существует стандарт безопасного кодирования CERT. Он предлагает примеры и совместимые решения:

int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[128];
  strcpy(prog_name, argv[0]);
  /* ... */
}

И их альтернатива:

int main(int argc, char *argv[]) {
  /* ... */
  char *prog_name = (char *)malloc(strlen(argv[0])+1);
  if (prog_name != NULL) {
    strcpy(prog_name, argv[0]);
  }
  else {
    /* Couldn't get the memory - recover */
  }
  /* ... */
}

Взят отсюда, 2-й пример .

Но, насколько я понимаю, это просто сложнее, больше кода, больше работы. Почему никто не меняет саму библиотеку? Или, по крайней мере, почему никто не предоставляет безопасную альтернативную библиотеку или функции, которые обрабатывают это правильно?

Спасибо за чтение, wishi

Ответы [ 7 ]

9 голосов
/ 27 января 2009

Функция Posix для этого (доступна почти на каждой системе) - strdup(). strcpy() используется, если вы не хотите выделять новую память и у вас уже есть буфер, который вы хотите использовать, но тогда вы лучше знаете, насколько велик этот буфер и соответствует ли строка в нем. Если вы не знаете, подходит ли строка, есть strncpy(), которая просто копирует заданное количество символов. Таким образом, вы можете ограничить количество копий до размера ваших буферов.

И, кроме того, существует множество библиотек sting, которые по-разному управляют размерами строк.

И так как вы пометили его C ++: существует std::string, который выполняет все управление памятью и не доставляет вам этих проблем.

2 голосов
/ 27 января 2009

функции l (strlcpy, strlcat) из OpenBSD обычно лучше, чем функции n , они быстрее и проще в использовании, но они нестандартные. Тем не менее, они имеют лицензию BSD, поэтому вы можете включить хорошо зарекомендовавшую себя реализацию в любую программу, чтобы вы могли быть кроссплатформенными и безопасными.

Для Windows, если вас не волнует переносимость, вы можете использовать функции * _s.

2 голосов
/ 27 января 2009

Использование strncpy:

#define BUFSIZE 127
int main(int argc, char *argv[]) {
  /* ... */
  char prog_name[BUFSIZE + 1];
  strncpy(prog_name, argv[0], BUFSIZE);
  progname[BUFSIZE]= '\0';
  /* ... */
}

Существуют *n* версии для большинства str* функций.

1 голос
/ 29 января 2009

Если я правильно понимаю, ваш реальный вопрос в том, почему функции API не стали более безопасными.

Одной из причин является то, что библиотека C является устаревшей (слишком поздно, чтобы изменить ее сейчас).

Основная причина, однако, заключается в том, что библиотека спроектирована так, чтобы быть минималистичной, так что она выполняет минимум и ответственность за правильность ее вызова лежит на пользователе Если бы он делал какие-либо чрезмерные проверки, то цена будет выплачиваться при каждом его вызове, даже если пользователь может по другим причинам заверить, что никаких проблем не возникнет. Это очень часто встречается во многих API.

При этом существует достаточно библиотек, которые предоставляют более безопасные альтернативы, они просто не являются частью стандартной библиотеки. Кроме того, многие люди, которые занимаются вещами более высокого уровня, работают с C ++, который имеет стандартные библиотеки классов для многих из этих вещей.

0 голосов
/ 29 января 2009

Может быть, вы найдете полезные ответы для чтения на этот вопрос

0 голосов
/ 27 января 2009
int main
(
    int argc, 
    char *argV[]
) 
{
   char prog_name[128];
   if (strlen(argV[0]) < sizeof(prog_name))
   {
       strcpy(prog_name, argV[0]);
   }
   else
   {
       printf("%s is too large for the internal buffer\n", argV[0]);
   }

   return 0;
}
0 голосов
/ 27 января 2009

На самом деле Microsoft предоставила безопасные альтернативы функциям CRT. Все, кого я знаю, ненавидят их и отключают предупреждение о том, что вы не должны использовать старые функции. Если вы хотите что-то безопасное, возможно, вам следует использовать C ++. А потом либо строки STL, либо что-то вроде Qt.

Ну, или вы переходите на платформы, такие как .NET или Java, которые обычно не страдают от этих проблем (ваше приложение может аварийно завершить работу, но нет способа внедрить код в ваше приложение через переполнение буфера).

Edit: С включенным Data Execution Prevention / NX (по умолчанию для Vista и .NET) это не должно быть проблемой и для традиционных платформ.

...