mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
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:
parent
6602b355c2
commit
a414f01ac2
20
lib/string.c
20
lib/string.c
@ -246,13 +246,17 @@ EXPORT_SYMBOL(strlcat);
|
||||
#undef strcmp
|
||||
int strcmp(const char *cs, const char *ct)
|
||||
{
|
||||
signed char __res;
|
||||
unsigned char c1, c2;
|
||||
|
||||
while (1) {
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
c1 = *cs++;
|
||||
c2 = *ct++;
|
||||
if (c1 != c2)
|
||||
return c1 < c2 ? -1 : 1;
|
||||
if (!c1)
|
||||
break;
|
||||
}
|
||||
return __res;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(strcmp);
|
||||
#endif
|
||||
@ -266,14 +270,18 @@ EXPORT_SYMBOL(strcmp);
|
||||
*/
|
||||
int strncmp(const char *cs, const char *ct, size_t count)
|
||||
{
|
||||
signed char __res = 0;
|
||||
unsigned char c1, c2;
|
||||
|
||||
while (count) {
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
c1 = *cs++;
|
||||
c2 = *ct++;
|
||||
if (c1 != c2)
|
||||
return c1 < c2 ? -1 : 1;
|
||||
if (!c1)
|
||||
break;
|
||||
count--;
|
||||
}
|
||||
return __res;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(strncmp);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user