summaryrefslogtreecommitdiff
path: root/lib/mbswidth.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-03-12 13:54:43 +0100
committerBruno Haible <bruno@clisp.org>2011-03-12 13:54:43 +0100
commit68d757e2cb228590d46961cbf3e9ec7d4460e335 (patch)
treeb5ce3979d3011fadfc29c4c954a013d0a744a9b4 /lib/mbswidth.c
parentb56b2e303252c4eac5cf7f702553d731f5bbfc4e (diff)
downloadgnulib-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.c42
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;
}