strncmp()表达式中的strlen()是否违背了使用strncmp()而不是strcmp()的目的?

时间:2013-02-14 22:11:48

标签: c buffer-overflow strcmp strncmp

根据我的理解,strcmp()(没有'n'),当在任一参数中看到空字符时,立即停止处理并返回结果。
因此,如果已知其中一个参数100%确定为空终止(例如,它是一个字符串文字),那么使用strncmp()(带'n')调用时没有任何安全优势。 strlen()作为将比较限制为已知字符串长度的第三个参数的一部分,因为strcmp()将永远不会读取比已知终止字符串中更多的字符。

事实上,在我看来,对前两个参数之一的长度参数为strncmp()的{​​{1}}的调用仅与strlen()的情况不同。通过评估strcmp()表达式,浪费了已知终止字符串大小的线性时间。

考虑:

示例代码A:

strlen()

示例代码B:

if (strcmp(user_input, "status") == 0)
    reply_with_status();

前者对后者有什么好处?因为我在其他人的代码中看到了很多

我对这些功能的运作方式存在缺陷吗?

6 个答案:

答案 0 :(得分:5)

在您的特定示例中,我会说使用strncmp是不利的,因为:

  • 无论如何使用strlen进行扫描
  • 重复字符串文字"status"
  • 添加1以确保字符串确实相等

所有这些都会增加混乱,如果它确实短于6个字符且包含与测试字符串相同的字符,那么在任何情况下都不会溢出user_input

那将是例外。如果您知道输入字符串的内存总是超过测试字符串中的字符数,那么请不要担心。否则,可能需要担心,或者至少要考虑它。 strncmp对于测试大缓冲区内的内容非常有用。

我更喜欢代码可读性。

答案 1 :(得分:4)

是的。如果在strncmp中使用strlen,它将遍历指针,直到它在字符串中看到null。这使它在功能上等同于strcmp。

答案 2 :(得分:4)

在你给出的特定情况下,它确实没用。然而,稍微改变是更常见的:

if (strncmp(user_input, "status", strlen("status")) == 0)
    reply_with_status();

此版本仅检查user_input 是否以"status"启动,因此它具有不同的语义。

答案 3 :(得分:2)

除了检查字符串的开头是否与输入匹配的技巧之外,strncmp仅在您不能100%确定字符串在其分配空间结束之前终止时才会有用。

因此,如果你有一个固定大小的缓冲区,你可以使用:

strncmp(user_input, "status", sizeof(user_input))

因此,确保您的比较不会溢出。

但是在这种情况下你必须要小心,因为如果你的user_input没有以null结尾,那么它将真正检查user_input是否与状态的开始匹配。

更好的方法可能是:

if (user_input[sizeof(user_input) - 1] != '\0') {
  // handle it, since it is _not_ equal to your string
  // unless filling the buffer is valid
}
else if (strcmp(user_input, "status")) { ... }

答案 4 :(得分:0)

现在,我同意这对使用strncmp()并不是特别有用,而且我在strcmp()中看不到任何好处。

但是,如果我们在+1之后移除strlen来更改代码,那么它就会开始变得有用。

 strncmp(user_input, "status", strlen("status"))

因为它将user_input的前6个字符与“状态”进行比较 - 这至少有时是有意义的。

所以,如果+1存在,它就变成了常规的strcmp - 这只是浪费时间来计算长度。但是没有+1,这是一个非常有用的比较(在适当的情况下)。

答案 5 :(得分:0)

strncmp()使用有限。如果在两个字符串中的任何一个上遇到NUL,则正常的strcmp()将停止。 (在这种情况下,字符串是不同的)Strncmp()将停止并返回零(“字符串在前N个字符中相等”)

stncmp()的一个可能用途是解析选项,直到非重要部分,例如

if (!strncmp("-st", argv[xx], 3)) {}

,对于“-string”或“-state”或“-st0”返回零,但为“-sadistic”。