diff options
author | Bruno Haible <bruno@clisp.org> | 2011-03-12 13:54:43 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2011-03-12 13:54:43 +0100 |
commit | 68d757e2cb228590d46961cbf3e9ec7d4460e335 (patch) | |
tree | b5ce3979d3011fadfc29c4c954a013d0a744a9b4 /lib/mbswidth.c | |
parent | b56b2e303252c4eac5cf7f702553d731f5bbfc4e (diff) | |
download | gnulib-68d757e2cb228590d46961cbf3e9ec7d4460e335.tar.gz |
wcswidth, mbswidth: Avoid integer overflow.
* lib/wcswidth.c: Include <limits.h>.
* lib/wcswidth-impl.h (wcswidth): Avoid 'int' overflow.
* lib/mbswidth.c: Include <limits.h>.
(mbsnwidth): Avoid 'int' overflow.
Reported by Jim Meyering.
Diffstat (limited to 'lib/mbswidth.c')
-rw-r--r-- | lib/mbswidth.c | 42 |
1 files changed, 34 insertions, 8 deletions
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 <wctype.h> +/* Get INT_MAX. */ +#include <limits.h> + /* 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; } |