Почему MSVC ++ считает “std:: strcat” “небезопасным"?(C++)

StackOverflow https://stackoverflow.com/questions/936468

  •  06-09-2019
  •  | 
  •  

Вопрос

Когда я пытаюсь делать подобные вещи, как это:

char* prefix = "Sector_Data\\sector";
char* s_num = "0";
std::strcat(prefix, s_num);
std::strcat(prefix, "\\");

и так далее, и тому подобное, я получаю предупреждение

warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead.

Почему strcat считается небезопасным, и есть ли способ избавиться от этого предупреждения без использования strcat_s ?

Кроме того, если единственный способ избавиться от предупреждения - использовать strcat_s, как это работает (с точки зрения синтаксиса:по-видимому, это не требует двух аргументов).

Это было полезно?

Решение

Потому что в буфере prefix может быть меньше места, чем вы копируете в него, что приведет к переполнению буфера.Следовательно, хакер может передать специально созданную строку, которая перезаписывает адрес возврата или другую важную память, и начать выполнение кода в контексте вашей программы.

strcat_s решает эту проблему, заставляя вас передавать длину буфера, в который вы копируете строку;при необходимости он усечет строку, чтобы убедиться, что буфер не переполнен.

погуглите strcat_s, чтобы точно узнать, как его использовать.

Другие советы

Если вы используете c ++, почему бы не избежать всего этого беспорядка и не использовать std::string.Тот же пример без каких-либо ошибок выглядел бы следующим образом:

std::string prefix = "Sector_Data\\sector";
prefix += "0";
prefix += "\\"

не нужно беспокоиться о размерах буфера и всем таком прочем.И если у вас есть API, который принимает const char *, вы можете просто использовать .c_str() Участник;

some_c_api(prefix.c_str());

Это одна из функций манипулирования строками в C / C ++, которая может приводить к ошибкам переполнения буфера.

Проблема в том, что функция не знает, каков размер буферов.Из документации MSDN:

Первый аргумент, strDestination, должен быть достаточно большим, чтобы вместить текущие strDestination и strSource объединенные и закрывающий '\0';в противном случае может произойти переполнение буфера.

strcat_s принимает дополнительный аргумент, указывающий ему размер буфера.Это позволит ему проверить размеры перед выполнением объединения и предотвратит переполнение.Видишь http://msdn.microsoft.com/en-us/library/d45bbxx4.aspx

Вы можете избавиться от этих предупреждений, добавив:

_CRT_SECURE_NO_WARNINGS

и

_SCL_SECURE_NO_WARNINGS

к определениям препроцессора вашего проекта.

Чтобы отключить предупреждение, вы можете сделать это.

#pragma warning(disable:4996)

кстати, я настоятельно рекомендую вам использовать strcat_s().

Потому что у него нет возможности проверить, будет ли строка назначения (префикс) в вашем случае записана за ее пределами.strcat по сути работает путем циклического копирования побайтно исходной строки в целевую.Он останавливается, когда видит значение "0" (обозначаемое '\ 0'), называемое нулевым терминалом.Поскольку C не имеет встроенной проверки границ, а dest str - это просто место в памяти, strcat будет продолжать работать до бесконечности, даже если он пронесется мимо исходного str или dest.у str нет нулевого терминала.

Приведенные выше решения зависят от конкретной платформы для вашей среды Windows.Если вы хотите что-то независимое от платформы, вам придется повозиться со strncat:

strncat(char* dest, const char* src, size_t count)

Это еще один вариант, если использовать его разумно.Вы можете использовать count, чтобы указать максимальное количество символов для копирования.Чтобы сделать это, вы должны выяснить, сколько места доступно в dest (сколько вы выделили - strlen(dest)) и передать это как count.

С strcat есть две проблемы.Во-первых, вы должны выполнить всю свою проверку вне функции, выполняя работу, которая почти такая же, как у функции:

if(pDest+strlen(pDest)+strlen(pScr) < destSize)

Вы должны пройти по всей длине обеих строк, просто чтобы убедиться, что они подойдут, прежде чем снова пройти по всей их длине, чтобы выполнить копирование.Из-за этого многие программисты просто предполагают, что это подойдет, и пропускают тест.Хуже того, может случиться так, что при первом написании кода он ГАРАНТИРОВАННО подойдет, но когда кто-то добавляет другой strcat или изменяет размер буфера или константу где-то еще в программе, у вас теперь возникают проблемы.

Другая проблема заключается в том, что КРОУ и pDst перекрываются.В зависимости от вашего компилятора strcat вполне может быть простым циклом, который проверяет символ за раз на наличие 0 в pSrc.Если pDst перезапишет это 0, то вы попадете в цикл, который будет выполняться до тех пор, пока ваша программа не выйдет из строя.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top