可能执行不好的strcmp

时间:2015-03-15 17:08:05

标签: c strcmp

我找到了strcmp函数的一个实现,我把它展示给了一个朋友,他说下面的“值得注意的是它并不总是返回两个不同字符之间的差异;它实际上允许返回提供的任何整数符号与字节之间的差异相同。“然后没有给我进一步的解释,代码是这个

int
strcmp(s1, s2)
    register const char *s1, *s2;
{
    while (*s1 == *s2++)
        if (*s1++ == 0)
            return (0);
    return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}

有人可以解释错误是什么吗?什么样的字符串会导致失败?

3 个答案:

答案 0 :(得分:5)

你朋友的意思是:strcmp返回一个大于,等于或小于0的整数。返回两个字符之间的实际差异并不是强制性的。但是,这样做不是错误。

这种实现的主要问题是:它使用K&R C,这是Brian Kernighan和Dennis Ritchie在 The C Programming Language 的第一版中使用的预标准C。你应该总是使用标准的C语言。

答案 1 :(得分:1)

这个strcmp不一定会返回两个字符串之间的真正差异。它要么返回一个正整数,要么返回一个负整数或零。

这种混乱导致MySQL等程序出现重大安全漏洞。

"问题是这些比较函数返回的值有时会被开发人员误解,所以他们会犯这样的错误,比如认为这些函数只能返回-1,0或1.或者,他们可能认为返回value可以安全地转换为较小的类型,例如char,但是他们没有意识到值的截断可能导致两个内存区域在它们不是时被认为是相等的。" [1]

看看这个patch from Wine's repo

+    ret = strcmp(file1, file2);
+    if (ret < 0) return -1;
+    if (ret > 0) return  1;
+    return  0;

参考文献: [1]

答案 2 :(得分:0)

这是strcmp()的苹果实现

int strcmp(const char *s1, const char *s2)
{
    for ( ; *s1 == *s2; s1++, s2++)
        if (*s1 == '\0')
            return 0;
    return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
}

这是jbox的版本

int strcmp(const char *s1, const char *s2)
{
    int ret = 0;

    while (!(ret = *(unsigned char *) s1 - *(unsigned char *) s2)
           && *s2) ++s1, ++s2;

   if (ret < 0) ret = -1;
   else if (ret > 0) ret = 1 ;

   return ret;

}

这是一个wiki实现

int strcmp(const char* s1, const char* s2)
{
    while(*s1 && (*s1==*s2))
        s1++,s2++;
    return *(const unsigned char*)s1-*(const unsigned char*)s2;
}

这是一个charsharp.com实现

int strcmp_ptr(char *src1, char *src2)
{
    int i=0;
    while((*src1!='\0') || (*src2!='\0'))
    {
        if(*src1 > *src2)
            return 1;
        if(*src1 < *src2)
            return -1;
        src1++;
        src2++;
    }
    return 0;
}

请注意它们都有效,并且都符合要求 正如strcmp的linux手册页中所述。 以下是手册页中有关返回值的内容:

“strcmp()和strncmp()函数返回一个小于等于的整数        如果找到s1(或其前n个字节),则为或者大于零,        分别小于,匹配或大于s2。“