History

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.

Linus Torvalds committed 16 years ago

Commit a414f011 parent 6602b351 file · +14 −6Browse files

Showing the changes to lib/string.c (1 of 1 file). Show all

Unified · Split

lib/string.c+14−6
@@ -246,13 +246,17 @@ EXPORT_SYMBOL(strlcat); · 245 unmodified lines
246246 #undef strcmp
247247 int strcmp(const char *cs, const char *ct)
248248 {
249− signed char __res;
249+ unsigned char c1, c2;
250250
251251 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)
253257 break;
254258 }
255− return __res;
259+ return 0;
256260 }
257261 EXPORT_SYMBOL(strcmp);
258262 #endif
@@ -266,14 +270,18 @@ EXPORT_SYMBOL(strcmp); · 7 unmodified lines
266270 */
267271 int strncmp(const char *cs, const char *ct, size_t count)
268272 {
269− signed char __res = 0;
273+ unsigned char c1, c2;
270274
271275 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)
273281 break;
274282 count--;
275283 }
276− return __res;
284+ return 0;
277285 }
278286 EXPORT_SYMBOL(strncmp);
279287 #endif