aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-11-18 16:31:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-11-18 20:18:13 -0500
commita414f01ac2899f273ef8fe98fa44158ac12793f2 (patch)
tree30a7ef8d7d2f8d4aca0781fa8785630fc1f6320d
parent6602b355c2cf8f4c628732827408606075288d28 (diff)
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>
-rw-r--r--lib/string.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/lib/string.c b/lib/string.c
index b19b87af65a3..e96421ab9a9a 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -246,13 +246,17 @@ EXPORT_SYMBOL(strlcat);
246#undef strcmp 246#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#endif 262#endif
@@ -266,14 +270,18 @@ EXPORT_SYMBOL(strcmp);
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#endif 287#endif