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>

+14 -6
+14 -6
lib/string.c
··· 246 246 #undef strcmp 247 247 int strcmp(const char *cs, const char *ct) 248 248 { 249 - signed char __res; 249 + unsigned char c1, c2; 250 250 251 251 while (1) { 252 - if ((__res = *cs - *ct++) != 0 || !*cs++) 252 + c1 = *cs++; 253 + c2 = *ct++; 254 + if (c1 != c2) 255 + return c1 < c2 ? -1 : 1; 256 + if (!c1) 253 257 break; 254 258 } 255 - return __res; 259 + return 0; 256 260 } 257 261 EXPORT_SYMBOL(strcmp); 258 262 #endif ··· 270 266 */ 271 267 int strncmp(const char *cs, const char *ct, size_t count) 272 268 { 273 - signed char __res = 0; 269 + unsigned char c1, c2; 274 270 275 271 while (count) { 276 - if ((__res = *cs - *ct++) != 0 || !*cs++) 272 + c1 = *cs++; 273 + c2 = *ct++; 274 + if (c1 != c2) 275 + return c1 < c2 ? -1 : 1; 276 + if (!c1) 277 277 break; 278 278 count--; 279 279 } 280 - return __res; 280 + return 0; 281 281 } 282 282 EXPORT_SYMBOL(strncmp); 283 283 #endif