From: Bruno Haible Date: Sat, 12 Mar 2011 12:54:43 +0000 (+0100) Subject: wcswidth, mbswidth: Avoid integer overflow. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=68d757e2cb228590d46961cbf3e9ec7d4460e335;p=pspp wcswidth, mbswidth: Avoid integer overflow. * lib/wcswidth.c: Include . * lib/wcswidth-impl.h (wcswidth): Avoid 'int' overflow. * lib/mbswidth.c: Include . (mbsnwidth): Avoid 'int' overflow. Reported by Jim Meyering. --- diff --git a/ChangeLog b/ChangeLog index 66c95a9a85..a3ddcef231 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-03-12 Bruno Haible + + wcswidth, mbswidth: Avoid integer overflow. + * lib/wcswidth.c: Include . + * lib/wcswidth-impl.h (wcswidth): Avoid 'int' overflow. + * lib/mbswidth.c: Include . + (mbsnwidth): Avoid 'int' overflow. + Reported by Jim Meyering. + 2011-03-12 Bruno Haible futimens, utimensat: Avoid endless recursion on Solaris 10. diff --git a/lib/mbswidth.c b/lib/mbswidth.c index 95f98dcd59..ad0eae086a 100644 --- a/lib/mbswidth.c +++ b/lib/mbswidth.c @@ -35,12 +35,14 @@ /* Get iswcntrl(). */ #include +/* Get INT_MAX. */ +#include + /* Returns the number of columns needed to represent the multibyte character string pointed to by STRING. If a non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is - the multibyte analogue of the wcswidth function. - If STRING is not of length < INT_MAX / 2, integer overflow can occur. */ + the multibyte analogue of the wcswidth function. */ int mbswidth (const char *string, int flags) { @@ -50,8 +52,7 @@ mbswidth (const char *string, int flags) /* Returns the number of columns needed to represent the multibyte character string pointed to by STRING of length NBYTES. If a non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is - specified, -1 is returned. - If NBYTES is not < INT_MAX / 2, integer overflow can occur. */ + specified, -1 is returned. */ int mbsnwidth (const char *string, size_t nbytes, int flags) { @@ -135,11 +136,22 @@ mbsnwidth (const char *string, size_t nbytes, int flags) w = wcwidth (wc); if (w >= 0) /* A printable multibyte character. */ - width += w; + { + if (w > INT_MAX - width) + goto overflow; + width += w; + } else /* An unprintable multibyte character. */ if (!(flags & MBSW_REJECT_UNPRINTABLE)) - width += (iswcntrl (wc) ? 0 : 1); + { + if (!iswcntrl (wc)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } else return -1; @@ -157,11 +169,25 @@ mbsnwidth (const char *string, size_t nbytes, int flags) unsigned char c = (unsigned char) *p++; if (isprint (c)) - width++; + { + if (width == INT_MAX) + goto overflow; + width++; + } else if (!(flags & MBSW_REJECT_UNPRINTABLE)) - width += (iscntrl (c) ? 0 : 1); + { + if (!iscntrl (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } else return -1; } return width; + + overflow: + return INT_MAX; } diff --git a/lib/wcswidth-impl.h b/lib/wcswidth-impl.h index dc1a60c532..865390c5e9 100644 --- a/lib/wcswidth-impl.h +++ b/lib/wcswidth-impl.h @@ -28,6 +28,8 @@ wcswidth (const wchar_t *s, size_t n) int width = wcwidth (c); if (width < 0) goto found_nonprinting; + if (width > INT_MAX - count) + goto overflow; count += width; } } @@ -35,4 +37,7 @@ wcswidth (const wchar_t *s, size_t n) found_nonprinting: return -1; + + overflow: + return INT_MAX; } diff --git a/lib/wcswidth.c b/lib/wcswidth.c index 3133c8445a..cdedf73ec9 100644 --- a/lib/wcswidth.c +++ b/lib/wcswidth.c @@ -20,4 +20,6 @@ /* Specification. */ #include +#include + #include "wcswidth-impl.h"