From a4ce14d54b63bdca11f707e322100dfaaa117943 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 30 Mar 2008 18:29:39 +0200 Subject: [PATCH] Fix buffer overrun. --- ChangeLog | 7 ++++ lib/vasnprintf.c | 119 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5225d25d5..3388d1665 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-03-30 Bruno Haible + + Fix buffer overrun. + * lib/vasnprintf.c (VASNPRINTF): If !USE_SNPRINTF && pad_ourselves: + Don't consider the width for tmp_length. Check count against tmp_length + before doing the padding. Ensure enough allocation during padding. + 2008-03-30 Eric Blake strtod touchups. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index bf3f5dc65..74b30374c 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -3656,6 +3656,44 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif + /* Decide whether to handle the precision ourselves. */ +#if NEED_PRINTF_UNBOUNDED_PRECISION + switch (dp->conversion) + { + case 'd': case 'i': case 'u': + case 'o': + case 'x': case 'X': case 'p': + prec_ourselves = has_precision && (precision > 0); + break; + default: + prec_ourselves = 0; + break; + } +#endif + + /* Decide whether to perform the padding ourselves. */ +#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) + switch (dp->conversion) + { +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need + to perform the padding after this conversion. Functions + with unistdio extensions perform the padding based on + character count rather than element count. */ + case 'c': case 's': +# endif +# if NEED_PRINTF_FLAG_ZERO + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': +# endif + pad_ourselves = 1; + break; + default: + pad_ourselves = prec_ourselves; + break; + } +#endif + #if !USE_SNPRINTF /* Allocate a temporary buffer of sufficient size for calling sprintf. */ @@ -3832,18 +3870,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, abort (); } + if (!pad_ourselves) + { # if ENABLE_UNISTDIO - /* Padding considers the number of characters, therefore the - number of elements after padding may be - > max (tmp_length, width) - but is certainly - <= tmp_length + width. */ - tmp_length = xsum (tmp_length, width); + /* Padding considers the number of characters, therefore + the number of elements after padding may be + > max (tmp_length, width) + but is certainly + <= tmp_length + width. */ + tmp_length = xsum (tmp_length, width); # else - /* Padding considers the number of elements, says POSIX. */ - if (tmp_length < width) - tmp_length = width; + /* Padding considers the number of elements, + says POSIX. */ + if (tmp_length < width) + tmp_length = width; # endif + } tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ } @@ -3864,44 +3906,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif - /* Decide whether to handle the precision ourselves. */ -#if NEED_PRINTF_UNBOUNDED_PRECISION - switch (dp->conversion) - { - case 'd': case 'i': case 'u': - case 'o': - case 'x': case 'X': case 'p': - prec_ourselves = has_precision && (precision > 0); - break; - default: - prec_ourselves = 0; - break; - } -#endif - - /* Decide whether to perform the padding ourselves. */ -#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) - switch (dp->conversion) - { -# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO - /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need - to perform the padding after this conversion. Functions - with unistdio extensions perform the padding based on - character count rather than element count. */ - case 'c': case 's': -# endif -# if NEED_PRINTF_FLAG_ZERO - case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': -# endif - pad_ourselves = 1; - break; - default: - pad_ourselves = prec_ourselves; - break; - } -#endif - /* Construct the format string for calling snprintf or sprintf. */ fbp = buf; @@ -4398,14 +4402,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if !DCHAR_IS_TCHAR -# if !USE_SNPRINTF +#if !USE_SNPRINTF if (count >= tmp_length) /* tmp_length was incorrectly calculated - fix the code above! */ abort (); -# endif +#endif +#if !DCHAR_IS_TCHAR /* Convert from TCHAR_T[] to DCHAR_T[]. */ if (dp->conversion == 'c' || dp->conversion == 's') { @@ -4523,7 +4527,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (w < width) { size_t pad = width - w; -# if USE_SNPRINTF + /* Make room for the result. */ if (xsum (count, pad) > allocated - length) { @@ -4533,12 +4537,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, xmax (xsum3 (length, count, pad), xtimes (allocated, 2)); +# if USE_SNPRINTF length += count; ENSURE_ALLOCATION (n); length -= count; +# else + ENSURE_ALLOCATION (n); +# endif } /* Here count + pad <= allocated - length. */ -# endif + { # if !DCHAR_IS_TCHAR || USE_SNPRINTF DCHAR_T * const rp = result + length; @@ -4599,13 +4607,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if DCHAR_IS_TCHAR && !USE_SNPRINTF - if (count >= tmp_length) - /* tmp_length was incorrectly calculated - fix the - code above! */ - abort (); -#endif - /* Here still count <= allocated - length. */ #if !DCHAR_IS_TCHAR || USE_SNPRINTF -- 2.11.0