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

Unified · Split

lib/string.c+14−6
@@ -246,13 +246,17 @@ EXPORT_SYMBOL(strlcat); · 245 unmodified lines
246#undef strcmp246#undef strcmp
247int strcmp(const char *cs, const char *ct)247int strcmp(const char *cs, const char *ct)
248{248{
249 signed char __res;249 unsigned char c1, c2;
250 250
251 while (1) {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 break;257 break;
254 }258 }
255 return __res;259 return 0;
256}260}
257EXPORT_SYMBOL(strcmp);261EXPORT_SYMBOL(strcmp);
258#endif262#endif
@@ -266,14 +270,18 @@ EXPORT_SYMBOL(strcmp); · 7 unmodified lines
266 */270 */
267int strncmp(const char *cs, const char *ct, size_t count)271int 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 while (count) {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 break;281 break;
274 count--;282 count--;
275 }283 }
276 return __res;284 return 0;
277}285}
278EXPORT_SYMBOL(strncmp);286EXPORT_SYMBOL(strncmp);
279#endif287#endif