Commit a414f01ac2899f273ef8fe98fa44158ac12793f2

Authored by Linus Torvalds
1 parent 6602b355c2

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>

Showing 1 changed file with 14 additions and 6 deletions Side-by-side Diff

... ... @@ -246,13 +246,17 @@
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
259 263  
260 264  
... ... @@ -266,14 +270,18 @@
266 270 */
267 271 int strncmp(const char *cs, const char *ct, size_t count)
268 272 {
269   - signed char __res = 0;
  273 + unsigned char c1, c2;
270 274  
271 275 while (count) {
272   - if ((__res = *cs - *ct++) != 0 || !*cs++)
  276 + c1 = *cs++;
  277 + c2 = *ct++;
  278 + if (c1 != c2)
  279 + return c1 < c2 ? -1 : 1;
  280 + if (!c1)
273 281 break;
274 282 count--;
275 283 }
276   - return __res;
  284 + return 0;
277 285 }
278 286 EXPORT_SYMBOL(strncmp);
279 287 #endif