C++ 有没有安全的strcmp?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1623769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:38:41  来源:igfitidea点击:

Is there any safe strcmp?

c++cstrcmp

提问by P-P

I made a function like this:

我做了一个这样的功能:

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

The problem is that sometimes, by mistake, arguments are passed which are not strings (meaning that p1or p2is not terminated with a null character). Then, strcmpcontinues comparing until it reaches non-accessible memory and crashes. Is there a safe version of strcmp? Or can I tell whether p1(and p2) is a string or not in a safe manner?

问题是有时会错误地传递不是字符串的参数(意味着p1p2不以空字符结尾)。然后,strcmp继续比较,直到到达不可访问的内存并崩溃。有安全版本strcmp吗?或者我可以以安全的方式判断p1(和p2)是否是字符串?

回答by Wernsey

No, there's no (standard) way to tell whether a char *actually points to valid memory.

不,没有(标准)方法可以判断 a 是否char *实际指向有效内存。

In your situation, it is better to use std::stringrather than char *s for all your strings, along with the overloaded ==operator. If you do this, the compiler would enforce type safety.

在您的情况下,最好对所有字符串使用std::string而不是char *s 以及重载==运算符。如果这样做,编译器将强制执行类型安全。

EDIT:As per the comments below if you find yourself in a situation where you sometimes pass char *s that may or may not be valid strings to functions that expect null-terminated strings then something is fundamentally wrong with your approach, so basically @janm's answer below.

编辑:根据下面的评论,如果您发现自己有时将char *可能是也可能不是有效字符串的 s传递给期望以空字符结尾的字符串的函数,那么您的方法从根本上就存在问题,所以基本上@janm 的回答如下.

回答by Igor Oks

In some cases std::strncmpcan solve your problem:

在某些情况下std::strncmp可以解决您的问题:

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

It compares up to num characters of the C string str1 to those of the C string str2.

它将 C 字符串 str1 的最多 num 个字符与 C 字符串 str2 的字符进行比较。



Also, take a look, what the US DHS National Cyber Security Division recommendson this matter:

另外,看看美国国土安全部国家网络安全部门对此事的建议

Ensure that strings are null terminated before passing into strcmp. This can be enforced by always placing a \0 in the last allocated byte of the buffer.

确保字符串在传入 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] = '
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 ) {}
'; str2[sizeof(str2)-1] = '##代码##'; /* Now the following is safe. */ if (strcmp(str1, str2)) { /* do something */ } else { /* do something else */ }

回答by janm

If you are passing strings to strcmp() that are not null terminated you have already lost. The fact that you have a string that is not null terminated (but should be) indicates that you have deeper issues in your code. You cannot change strcmp() to safely deal with this problem.

如果您向 strcmp() 传递非空终止的字符串,则您已经丢失了。您有一个不是空终止(但应该是)的字符串这一事实表明您的代码中存在更深层次的问题。您不能更改 strcmp() 来安全地处理此问题。

You should be writing your code so that can never happen. Start by using the string class. At the boundaries where you take data into your code you need to make sure you deal with the exceptional cases; if you get too much data you need to Do The Right Thing. That does not involve running off the end of your buffer. If you must perform I/O into a C style buffer, use functions where you specify the length of the buffer and detect and deal with cases where the buffer is not large enough at that point.

你应该编写你的代码,这样就永远不会发生。首先使用字符串类。在将数据带入代码的边界处,您需要确保处理异常情况;如果您获得太多数据,您需要做正确的事情。这不涉及跑掉缓冲区的末尾。如果必须对 C 样式缓冲区执行 I/O,请使用指定缓冲区长度的函数,并检测和处理此时缓冲区不够大的情况。

回答by sharptooth

There's no cure for this that is portable. The convention states that there's an extra character holding a null character that belongs to the same correctly allocated block of memory as the string itself. Either this convention is followed and everything's fine or undefined behaviour occurs.

没有办法治愈这种便携性。约定指出,有一个额外的字符包含一个空字符,该字符与字符串本身属于同一个正确分配的内存块。要么遵循此约定,要么发生一切正常或未定义的行为。

If you know the length of the string you compare against you can use strncmp()but his will not help if the string passed to your code is actually shorter than the string you compare against.

如果您知道与您比较的字符串的长度,您可以使用,strncmp()但如果传递给您的代码的字符串实际上比您比较的字符串短,他将无济于事。

回答by Satbir

you can use strncmp, But if possible use std::string to avoid many problems :)

您可以使用 strncmp,但如果可能,请使用 std::string 来避免许多问题:)

回答by Paolo Tedesco

You can put an upper limit on the number of characters to be compared using the strncmpfunction.

您可以使用strncmp函数设置要比较的字符数的上限。

回答by David Allan Finch

There is no best answer to this as you can't verify the char* is a string. The only solution is to create a type and use it for string for example str::string or create your own if you want something lighter. ie

对此没有最佳答案,因为您无法验证 char* 是字符串。唯一的解决方案是创建一个类型并将其用于字符串,例如 str::string 或者如果您想要更轻的东西,则创建自己的类型。IE

##代码##

回答by RED SOFT ADAIR

You dont write, what platform you are using. Windows has the following functions:

你不写,你用的是什么平台。Windows 具有以下功能:

IsBadStringPtrmight be what you are looking for, if you are using windows.

IsBadStringPtr如果您使用的是windows,可能就是您要找的东西。