diff options
author | Bruno Haible <bruno@clisp.org> | 2003-11-17 15:34:21 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2009-06-23 12:11:18 +0200 |
commit | 633ad4418ab3693ba8d05c4027be6ede0361c9f4 (patch) | |
tree | c7293544627db2e02d3eaada0453f3de1219958d /gettext-runtime/intl | |
parent | f69ac5b2c0d5f4d386d7e2afe0d5650e8b104d28 (diff) | |
download | external_gettext-633ad4418ab3693ba8d05c4027be6ede0361c9f4.zip external_gettext-633ad4418ab3693ba8d05c4027be6ede0361c9f4.tar.gz external_gettext-633ad4418ab3693ba8d05c4027be6ede0361c9f4.tar.bz2 |
Protect against address arithmetic overflow.
Diffstat (limited to 'gettext-runtime/intl')
-rw-r--r-- | gettext-runtime/intl/ChangeLog | 30 | ||||
-rw-r--r-- | gettext-runtime/intl/Makefile.in | 3 | ||||
-rw-r--r-- | gettext-runtime/intl/printf-args.c | 2 | ||||
-rw-r--r-- | gettext-runtime/intl/printf-args.h | 5 | ||||
-rw-r--r-- | gettext-runtime/intl/printf-parse.c | 97 | ||||
-rw-r--r-- | gettext-runtime/intl/printf-parse.h | 17 | ||||
-rw-r--r-- | gettext-runtime/intl/vasnprintf.c | 118 | ||||
-rw-r--r-- | gettext-runtime/intl/wprintf-parse.h | 15 |
8 files changed, 193 insertions, 94 deletions
diff --git a/gettext-runtime/intl/ChangeLog b/gettext-runtime/intl/ChangeLog index 2ae50e5..484836c 100644 --- a/gettext-runtime/intl/ChangeLog +++ b/gettext-runtime/intl/ChangeLog @@ -1,3 +1,33 @@ +2003-11-16 Paul Eggert <eggert@twinsun.com> + Bruno Haible <bruno@clisp.org> + + Protect against address arithmetic overflow. + * printf-args.h: Include stddef.h. + (arguments): Change type of field 'count' to size_t. + * printf-args.c (printf_fetchargs): Use size_t instead of + 'unsigned int' where appropriate. + * printf-parse.h: Include sys/types.h. + (char_directive): Change type of *arg_index fields to ssize_t. + (char_directives): Change type of fields 'count', max_*_length to + size_t. + * wprintf-parse.h: Include sys/types.h. + (wchar_t_directive): Change type of *arg_index fields to ssize_t. + (wchar_t_directives): Change type of fields 'count', max_*_length to + size_t. + * printf-parse.c: Include sys/types.h and xsize.h. + (SSIZE_MAX): Define fallback value. + (PRINTF_PARSE): Use size_t instead of 'unsigned int' and ssize_t + instead of 'int' where appropriate. Check a_allocated, d_allocated + against overflow. Reject %m$ argument numbers > SSIZE_MAX + 1. + * vasnprintf.c: Include xsize.h. + (VASNPRINTF): Use size_t instead of 'unsigned int' where appropriate. + Check alloca, malloc, realloc, ENSURE_ALLOCATION arguments against + overflow. Avoid wraparound when converting a width or precision from + decimal to binary. + * xsize.h: New file, from gnulib. + * Makefile.in (HEADERS): Add xsize.h. + (printf.$lo): Depend on it. + 2003-11-16 Bruno Haible <bruno@clisp.org> * libgnuintl.h.in (_INTL_REDIRECT_ASM): Don't define on AIX with gcc 2. diff --git a/gettext-runtime/intl/Makefile.in b/gettext-runtime/intl/Makefile.in index 172d61b..1517a43 100644 --- a/gettext-runtime/intl/Makefile.in +++ b/gettext-runtime/intl/Makefile.in @@ -73,6 +73,7 @@ HEADERS = \ eval-plural.h \ localcharset.h \ relocatable.h \ + xsize.h \ printf-args.h printf-args.c \ printf-parse.h wprintf-parse.h printf-parse.c \ vasnprintf.h vasnwprintf.h vasnprintf.c \ @@ -424,7 +425,7 @@ dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.h dcigettext.$lo: $(srcdir)/eval-plural.h localcharset.$lo: $(srcdir)/localcharset.h localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h -printf.$lo: $(srcdir)/printf-args.h $(srcdir)/printf-args.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/printf-parse.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/vasnprintf.c +printf.$lo: $(srcdir)/printf-args.h $(srcdir)/printf-args.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/xsize.h $(srcdir)/printf-parse.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/vasnprintf.c tags: TAGS diff --git a/gettext-runtime/intl/printf-args.c b/gettext-runtime/intl/printf-args.c index f391974..f6f3219 100644 --- a/gettext-runtime/intl/printf-args.c +++ b/gettext-runtime/intl/printf-args.c @@ -29,7 +29,7 @@ STATIC int printf_fetchargs (va_list args, arguments *a) { - unsigned int i; + size_t i; argument *ap; for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) diff --git a/gettext-runtime/intl/printf-args.h b/gettext-runtime/intl/printf-args.h index 35114a8..f11e64c 100644 --- a/gettext-runtime/intl/printf-args.h +++ b/gettext-runtime/intl/printf-args.h @@ -19,6 +19,9 @@ #ifndef _PRINTF_ARGS_H #define _PRINTF_ARGS_H +/* Get size_t. */ +#include <stddef.h> + /* Get wchar_t. */ #ifdef HAVE_WCHAR_T # include <stddef.h> @@ -117,7 +120,7 @@ argument; typedef struct { - unsigned int count; + size_t count; argument *arg; } arguments; diff --git a/gettext-runtime/intl/printf-parse.c b/gettext-runtime/intl/printf-parse.c index ff61c17..d760960 100644 --- a/gettext-runtime/intl/printf-parse.c +++ b/gettext-runtime/intl/printf-parse.c @@ -30,6 +30,9 @@ /* Get size_t, NULL. */ #include <stddef.h> +/* Get ssize_t. */ +#include <sys/types.h> + /* Get intmax_t. */ #if HAVE_STDINT_H_WITH_UINTMAX # include <stdint.h> @@ -41,6 +44,13 @@ /* malloc(), realloc(), free(). */ #include <stdlib.h> +/* Checked size_t computations. */ +#include "xsize.h" + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + #if WIDE_CHAR_VERSION # define PRINTF_PARSE wprintf_parse # define CHAR_T wchar_t @@ -60,11 +70,11 @@ int PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) { const CHAR_T *cp = format; /* pointer into format */ - int arg_posn = 0; /* number of regular arguments consumed */ - unsigned int d_allocated; /* allocated elements of d->dir */ - unsigned int a_allocated; /* allocated elements of a->arg */ - unsigned int max_width_length = 0; - unsigned int max_precision_length = 0; + ssize_t arg_posn = 0; /* number of regular arguments consumed */ + size_t d_allocated; /* allocated elements of d->dir */ + size_t a_allocated; /* allocated elements of a->arg */ + size_t max_width_length = 0; + size_t max_precision_length = 0; d->count = 0; d_allocated = 1; @@ -79,16 +89,22 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) #define REGISTER_ARG(_index_,_type_) \ { \ - unsigned int n = (_index_); \ + size_t n = (_index_); \ if (n >= a_allocated) \ { \ + size_t memory_size; \ argument *memory; \ - a_allocated = 2 * a_allocated; \ + \ + a_allocated = xtimes (a_allocated, 2); \ if (a_allocated <= n) \ - a_allocated = n + 1; \ + a_allocated = xsum (n, 1); \ + memory_size = xtimes (a_allocated, sizeof (argument)); \ + if (size_overflow_p (memory_size)) \ + /* Overflow, would lead to out of memory. */ \ + goto error; \ memory = (a->arg \ - ? realloc (a->arg, a_allocated * sizeof (argument)) \ - : malloc (a_allocated * sizeof (argument))); \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ if (memory == NULL) \ /* Out of memory. */ \ goto error; \ @@ -108,7 +124,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) CHAR_T c = *cp++; if (c == '%') { - int arg_index = -1; + ssize_t arg_index = -1; DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ /* Initialize the next directive. */ @@ -131,13 +147,16 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) ; if (*np == '$') { - unsigned int n = 0; + size_t n = 0; for (np = cp; *np >= '0' && *np <= '9'; np++) - n = 10 * n + (*np - '0'); + n = xsum (xtimes (n, 10), *np - '0'); if (n == 0) /* Positional argument 0. */ goto error; + if (size_overflow_p (n) || n - 1 > SSIZE_MAX) + /* n too large, would lead to out of memory later. */ + goto error; arg_index = n - 1; cp = np + 1; } @@ -198,24 +217,32 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) ; if (*np == '$') { - unsigned int n = 0; + size_t n = 0; for (np = cp; *np >= '0' && *np <= '9'; np++) - n = 10 * n + (*np - '0'); + n = xsum (xtimes (n, 10), *np - '0'); if (n == 0) /* Positional argument 0. */ goto error; + if (size_overflow_p (n) || n - 1 > SSIZE_MAX) + /* n too large, would lead to out of memory later. */ + goto error; dp->width_arg_index = n - 1; cp = np + 1; } } if (dp->width_arg_index < 0) - dp->width_arg_index = arg_posn++; + { + dp->width_arg_index = arg_posn++; + if (dp->width_arg_index < 0) + /* arg_posn wrapped around at SSIZE_MAX. */ + goto error; + } REGISTER_ARG (dp->width_arg_index, TYPE_INT); } else if (*cp >= '0' && *cp <= '9') { - unsigned int width_length; + size_t width_length; dp->width_start = cp; for (; *cp >= '0' && *cp <= '9'; cp++) @@ -247,24 +274,33 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) ; if (*np == '$') { - unsigned int n = 0; + size_t n = 0; for (np = cp; *np >= '0' && *np <= '9'; np++) - n = 10 * n + (*np - '0'); + n = xsum (xtimes (n, 10), *np - '0'); if (n == 0) /* Positional argument 0. */ goto error; + if (size_overflow_p (n) || n - 1 > SSIZE_MAX) + /* n too large, would lead to out of memory + later. */ + goto error; dp->precision_arg_index = n - 1; cp = np + 1; } } if (dp->precision_arg_index < 0) - dp->precision_arg_index = arg_posn++; + { + dp->precision_arg_index = arg_posn++; + if (dp->precision_arg_index < 0) + /* arg_posn wrapped around at SSIZE_MAX. */ + goto error; + } REGISTER_ARG (dp->precision_arg_index, TYPE_INT); } else { - unsigned int precision_length; + size_t precision_length; dp->precision_start = cp - 1; for (; *cp >= '0' && *cp <= '9'; cp++) @@ -457,7 +493,12 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) { dp->arg_index = arg_index; if (dp->arg_index < 0) - dp->arg_index = arg_posn++; + { + dp->arg_index = arg_posn++; + if (dp->arg_index < 0) + /* arg_posn wrapped around at SSIZE_MAX. */ + goto error; + } REGISTER_ARG (dp->arg_index, type); } dp->conversion = c; @@ -467,10 +508,18 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) d->count++; if (d->count >= d_allocated) { + size_t memory_size; DIRECTIVE *memory; - d_allocated = 2 * d_allocated; - memory = realloc (d->dir, d_allocated * sizeof (DIRECTIVE)); + d_allocated = xtimes (d_allocated, 2); + if (size_overflow_p (d_allocated)) + /* Overflow, would lead to out of memory. */ + goto error; + memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + goto error; + memory = realloc (d->dir, memory_size); if (memory == NULL) /* Out of memory. */ goto error; diff --git a/gettext-runtime/intl/printf-parse.h b/gettext-runtime/intl/printf-parse.h index 97e432a..754aaf2 100644 --- a/gettext-runtime/intl/printf-parse.h +++ b/gettext-runtime/intl/printf-parse.h @@ -1,5 +1,5 @@ /* Parse printf format string. - Copyright (C) 1999, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -21,6 +21,9 @@ #include "printf-args.h" +/* Get ssize_t. */ +#include <sys/types.h> + /* Flags */ #define FLAG_GROUP 1 /* ' flag */ @@ -38,22 +41,22 @@ typedef struct int flags; const char* width_start; const char* width_end; - int width_arg_index; + ssize_t width_arg_index; const char* precision_start; const char* precision_end; - int precision_arg_index; + ssize_t precision_arg_index; char conversion; /* d i o u x X f e E g G c s p n U % but not C S */ - int arg_index; + ssize_t arg_index; } char_directive; /* A parsed format string. */ typedef struct { - unsigned int count; + size_t count; char_directive *dir; - unsigned int max_width_length; - unsigned int max_precision_length; + size_t max_width_length; + size_t max_precision_length; } char_directives; diff --git a/gettext-runtime/intl/vasnprintf.c b/gettext-runtime/intl/vasnprintf.c index 5a37a0f..1415a6f 100644 --- a/gettext-runtime/intl/vasnprintf.c +++ b/gettext-runtime/intl/vasnprintf.c @@ -49,6 +49,9 @@ # include "printf-parse.h" #endif +/* Checked size_t computations. */ +#include "xsize.h" + /* For those losing systems which don't have 'alloca' we have to add some additional code emulating it. */ #ifdef HAVE_ALLOCA @@ -137,11 +140,12 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } { + size_t buf_neededlength = + xsum4 (7, d.max_width_length, d.max_precision_length, 6); CHAR_T *buf = - (CHAR_T *) alloca ((7 + d.max_width_length + d.max_precision_length + 6) - * sizeof (CHAR_T)); + (CHAR_T *) alloca (xtimes (buf_neededlength, sizeof (CHAR_T))); const CHAR_T *cp; - unsigned int i; + size_t i; DIRECTIVE *dp; /* Output string accumulator. */ CHAR_T *result; @@ -163,28 +167,26 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar result is either == resultbuf or == NULL or malloc-allocated. If length > 0, then result != NULL. */ + /* Ensures that allocated >= needed. Aborts through a jump to + out_of_memory if needed is SIZE_MAX or otherwise too big. */ #define ENSURE_ALLOCATION(needed) \ if ((needed) > allocated) \ { \ + size_t memory_size; \ CHAR_T *memory; \ \ - allocated = (allocated > 0 ? 2 * allocated : 12); \ + allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ if ((needed) > allocated) \ allocated = (needed); \ + memory_size = xtimes (allocated, sizeof (CHAR_T)); \ + if (size_overflow_p (memory_size)) \ + goto out_of_memory; \ if (result == resultbuf || result == NULL) \ - memory = (CHAR_T *) malloc (allocated * sizeof (CHAR_T)); \ + memory = (CHAR_T *) malloc (memory_size); \ else \ - memory = (CHAR_T *) realloc (result, allocated * sizeof (CHAR_T)); \ - \ + memory = (CHAR_T *) realloc (result, memory_size); \ if (memory == NULL) \ - { \ - if (!(result == resultbuf || result == NULL)) \ - free (result); \ - freea (buf); \ - CLEANUP (); \ - errno = ENOMEM; \ - return NULL; \ - } \ + goto out_of_memory; \ if (result == resultbuf && length > 0) \ memcpy (memory, result, length * sizeof (CHAR_T)); \ result = memory; \ @@ -195,10 +197,11 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (cp != dp->dir_start) { size_t n = dp->dir_start - cp; + size_t augmented_length = xsum (length, n); - ENSURE_ALLOCATION (length + n); + ENSURE_ALLOCATION (augmented_length); memcpy (result + length, cp, n * sizeof (CHAR_T)); - length += n; + length = augmented_length; } if (i == d.count) break; @@ -206,11 +209,14 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar /* Execute a single directive. */ if (dp->conversion == '%') { + size_t augmented_length; + if (!(dp->arg_index < 0)) abort (); - ENSURE_ALLOCATION (length + 1); + augmented_length = xsum (length, 1); + ENSURE_ALLOCATION (augmented_length); result[length] = '%'; - length += 1; + length = augmented_length; } else { @@ -249,15 +255,15 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar unsigned int prefix_count; int prefixes[2]; #if !USE_SNPRINTF - unsigned int tmp_length; + size_t tmp_length; CHAR_T tmpbuf[700]; CHAR_T *tmp; /* Allocate a temporary buffer of sufficient size for calling sprintf. */ { - unsigned int width; - unsigned int precision; + size_t width; + size_t precision; width = 0; if (dp->width_start != dp->width_end) @@ -269,14 +275,14 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) abort (); arg = a.arg[dp->width_arg_index].a.a_int; - width = (arg < 0 ? -arg : arg); + width = (arg < 0 ? (unsigned int) (-arg) : arg); } else { const CHAR_T *digitp = dp->width_start; do - width = width * 10 + (*digitp++ - '0'); + width = xsum (xtimes (width, 10), *digitp++ - '0'); while (digitp != dp->width_end); } } @@ -299,7 +305,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar precision = 0; do - precision = precision * 10 + (*digitp++ - '0'); + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); while (digitp != dp->precision_end); } } @@ -400,7 +406,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar * 2 /* estimate for FLAG_GROUP */ ) + 1 /* turn floor into ceil */ - + precision + 10; /* sign, decimal point etc. */ else # endif @@ -410,15 +415,15 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar * 2 /* estimate for FLAG_GROUP */ ) + 1 /* turn floor into ceil */ - + precision + 10; /* sign, decimal point etc. */ + tmp_length = xsum (tmp_length, precision); break; case 'e': case 'E': case 'g': case 'G': case 'a': case 'A': tmp_length = - precision - + 12; /* sign, decimal point, exponent etc. */ + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); break; case 'c': @@ -433,14 +438,14 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar case 's': # ifdef HAVE_WCHAR_T if (type == TYPE_WIDE_STRING) -# if WIDE_CHAR_VERSION - tmp_length = - local_wcslen (a.arg[dp->arg_index].a.a_wide_string); -# else - tmp_length = - local_wcslen (a.arg[dp->arg_index].a.a_wide_string) - * MB_CUR_MAX; + { + tmp_length = + local_wcslen (a.arg[dp->arg_index].a.a_wide_string); + +# if !WIDE_CHAR_VERSION + tmp_length = xtimes (tmp_length, MB_CUR_MAX); # endif + } else # endif tmp_length = strlen (a.arg[dp->arg_index].a.a_string); @@ -462,24 +467,22 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (tmp_length < width) tmp_length = width; - tmp_length++; /* account for trailing NUL */ + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ } if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) tmp = tmpbuf; else { - tmp = (CHAR_T *) malloc (tmp_length * sizeof (CHAR_T)); + size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (CHAR_T *) malloc (tmp_memsize); if (tmp == NULL) - { - /* Out of memory. */ - if (!(result == resultbuf || result == NULL)) - free (result); - freea (buf); - CLEANUP (); - errno = ENOMEM; - return NULL; - } + /* Out of memory. */ + goto out_of_memory; } #endif @@ -565,7 +568,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar #if USE_SNPRINTF /* Prepare checking whether snprintf returns the count via %n. */ - ENSURE_ALLOCATION (length + 1); + ENSURE_ALLOCATION (xsum (length, 1)); result[length] = '\0'; #endif @@ -770,7 +773,8 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar *and* it returns -1 (rather than the length that would have been required) when the buffer is too small. */ - size_t bigger_need = 2 * allocated + 12; + size_t bigger_need = + xsum (xtimes (allocated, 2), 12); ENSURE_ALLOCATION (bigger_need); continue; } @@ -804,10 +808,8 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar /* Need at least count bytes. But allocate proportionally, to avoid looping eternally if snprintf() reports a too small count. */ - size_t n = length + count; - - if (n < 2 * allocated) - n = 2 * allocated; + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); ENSURE_ALLOCATION (n); #if USE_SNPRINTF @@ -832,7 +834,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } /* Add the final NUL. */ - ENSURE_ALLOCATION (length + 1); + ENSURE_ALLOCATION (xsum (length, 1)); result[length] = '\0'; if (result != resultbuf && length + 1 < allocated) @@ -849,6 +851,14 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar CLEANUP (); *lengthp = length; return result; + + out_of_memory: + if (!(result == resultbuf || result == NULL)) + free (result); + freea (buf); + CLEANUP (); + errno = ENOMEM; + return NULL; } } diff --git a/gettext-runtime/intl/wprintf-parse.h b/gettext-runtime/intl/wprintf-parse.h index 83ebbf0..549865f 100644 --- a/gettext-runtime/intl/wprintf-parse.h +++ b/gettext-runtime/intl/wprintf-parse.h @@ -21,6 +21,9 @@ #include "printf-args.h" +/* Get ssize_t. */ +#include <sys/types.h> + /* Flags */ #define FLAG_GROUP 1 /* ' flag */ @@ -38,22 +41,22 @@ typedef struct int flags; const wchar_t* width_start; const wchar_t* width_end; - int width_arg_index; + ssize_t width_arg_index; const wchar_t* precision_start; const wchar_t* precision_end; - int precision_arg_index; + ssize_t precision_arg_index; wchar_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */ - int arg_index; + ssize_t arg_index; } wchar_t_directive; /* A parsed format string. */ typedef struct { - unsigned int count; + size_t count; wchar_t_directive *dir; - unsigned int max_width_length; - unsigned int max_precision_length; + size_t max_width_length; + size_t max_precision_length; } wchar_t_directives; |