Подтвердить что ты не робот

Есть ли безопасный strcmp?

Я сделал такую ​​функцию:

bool IsSameString(char* p1, char* p2) 
{
     return 0 == strcmp(p1, p2);
}

Проблема заключается в том, что иногда, по ошибке, передаются аргументы, которые не являются строками (это означает, что p1 или p2 не заканчивается нулевым символом). Затем strcmp продолжает сравнивать, пока не достигнет недоступной памяти и сработает. Есть ли безопасная версия strcmp? Или я могу сказать, является ли p1p2) строкой или нет в безопасном режиме?

4b9b3361

Ответ 1

Нет, нет (стандартного) способа определить, действительно ли char * указывает на действительную память.

В вашей ситуации лучше использовать std::string вместо char * для всех ваших строк вместе с перегруженным оператором ==. Если вы это сделаете, компилятор обеспечит безопасность типов.

РЕДАКТИРОВАТЬ: В соответствии с приведенными ниже комментариями, если вы оказываетесь в ситуации, когда вы иногда проходите char *, которые могут или не могут быть действительными строками для функций, которые ожидают строки с нулевым завершением, тогда что-то есть в корне неправильно с вашим подходом, поэтому в основном @janm ответьте ниже.

Ответ 2

В некоторых случаях std::strncmp может решить вашу проблему:

int strncmp ( const char * str1, const char * str2, size_t num ); 

Он сравнивает до num символов строки C str1 с символами строки C str2.


Кроме того, посмотрите, что US DHS National Cyber ​​Security Division рекомендует по этому вопросу:

Убедитесь, что строки переданы в нуль до перехода в strcmp. Это может быть принудительно, всегда помещая \0 в последний выделенный байт буфера.

char str1[] ="something";
char str2[] = "another thing";
/* In this case we know strings are null terminated. Pretend we don't. */
str1[sizeof(str1)-1] = '\0';
str2[sizeof(str2)-1] = '\0';
/* Now the following is safe. */
if (strcmp(str1, str2)) { /* do something */ } else { /* do something else */ }

Ответ 3

Если вы передаете строки strcmp(), которые не завершены нулем, вы уже потеряли. Тот факт, что у вас есть строка, которая не завершена нулем (но должна быть), указывает на то, что у вас есть более глубокие проблемы в вашем коде. Вы не можете изменить strcmp(), чтобы безопасно справиться с этой проблемой.

Вы должны писать свой код, чтобы этого никогда не было. Начните с использования класса string. На границах, где вы берете данные в свой код, вы должны убедиться, что имеете дело с исключительными случаями; если вы получаете слишком много данных, вам нужно сделать правильную вещь. Это не связано с запуском конца вашего буфера. Если вы должны выполнять ввод-вывод в буфере стиля C, используйте функции, в которых вы указываете длину буфера, и обнаруживаете и обрабатываете случаи, когда буфер недостаточно велик в этой точке.

Ответ 4

Там нет лекарств, которые переносятся. В соглашении говорится, что дополнительный символ содержит нулевой символ, принадлежащий тому же правильно выделенному блоку памяти, что и сама строка. Выполняется либо это соглашение, и все мелкие или undefined поведение.

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

Ответ 5

вы можете использовать strncmp, но если возможно, используйте std::string, чтобы избежать многих проблем:)

Ответ 6

Вы можете установить верхний предел количества сопоставляемых символов, используя функцию strncmp.

Ответ 7

Вы не пишете, какую платформу вы используете. Windows выполняет следующие функции:

IsBadStringPtr может быть тем, что вы ищете, если вы используете окна.

Ответ 8

Нет лучшего ответа на этот вопрос, поскольку вы не можете проверить, что char * - это строка. Единственное решение - создать тип и использовать его для строки, например str:: string, или создать свой собственный, если вы хотите что-то более легкое. то есть

struct MyString
  {
  MyString() : str(0), len(0) {}
  MyString( char* x ) { len = strlen(x); str = strdup(x); }
  ⁓MyString() { if(str) free(str); }
  char* str;
  size_t len;
  };

bool IsSameString(MyString& p1, MyString& p2) 
  {
  return 0 == strcmp(p1.str, p2.str);
  }


MyString str1("test");
MyString str2("test");

if( IsSameString( str1, str2 ) {}