strcmp: fix overflow and possibly signedness error

Doing the strcmp return value as

	signed char __res = *cs - *ct;

is wrong for two reasons.  The subtraction can overflow because __res
doesn't use a type big enough.  Moreover the compared bytes should be
interpreted as unsigned char as specified by POSIX.

The same problem is fixed in strncmp.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Cc: Michael Buesch <mb@bu3sch.de>
Cc: Andreas Schwab <schwab@linux-m68k.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2009-11-18 22:31:52 +01:00
parent 6602b355c2
commit a414f01ac2

View file

@ -246,13 +246,17 @@ EXPORT_SYMBOL(strlcat);
#undef strcmp #undef strcmp
int strcmp(const char *cs, const char *ct) int strcmp(const char *cs, const char *ct)
{ {
signed char __res; unsigned char c1, c2;
while (1) { while (1) {
if ((__res = *cs - *ct++) != 0 || !*cs++) c1 = *cs++;
c2 = *ct++;
if (c1 != c2)
return c1 < c2 ? -1 : 1;
if (!c1)
break; break;
} }
return __res; return 0;
} }
EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcmp);
#endif #endif
@ -266,14 +270,18 @@ EXPORT_SYMBOL(strcmp);
*/ */
int strncmp(const char *cs, const char *ct, size_t count) int strncmp(const char *cs, const char *ct, size_t count)
{ {
signed char __res = 0; unsigned char c1, c2;
while (count) { while (count) {
if ((__res = *cs - *ct++) != 0 || !*cs++) c1 = *cs++;
c2 = *ct++;
if (c1 != c2)
return c1 < c2 ? -1 : 1;
if (!c1)
break; break;
count--; count--;
} }
return __res; return 0;
} }
EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strncmp);
#endif #endif