This fixes a buffer overrun on OSF/1 4.0 and Solaris 2.5. Nothing to worry about for the majority of the platforms.
2008-03-30 Bruno Haible <[EMAIL PROTECTED]> 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. *** lib/vasnprintf.c.orig 2008-03-30 17:47:26.000000000 +0200 --- lib/vasnprintf.c 2008-03-30 17:43:05.000000000 +0200 *************** *** 3656,3661 **** --- 3656,3699 ---- } #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,3849 **** abort (); } # 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); # else ! /* 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 */ } --- 3870,3891 ---- 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); # else ! /* 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,3907 **** } #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; --- 3906,3911 ---- *************** *** 4398,4411 **** } #endif ! #if !DCHAR_IS_TCHAR ! # if !USE_SNPRINTF if (count >= tmp_length) /* tmp_length was incorrectly calculated - fix the code above! */ abort (); ! # endif /* Convert from TCHAR_T[] to DCHAR_T[]. */ if (dp->conversion == 'c' || dp->conversion == 's') { --- 4402,4415 ---- } #endif ! #if !USE_SNPRINTF if (count >= tmp_length) /* tmp_length was incorrectly calculated - fix the code above! */ abort (); ! #endif + #if !DCHAR_IS_TCHAR /* Convert from TCHAR_T[] to DCHAR_T[]. */ if (dp->conversion == 'c' || dp->conversion == 's') { *************** *** 4523,4529 **** if (w < width) { size_t pad = width - w; ! # if USE_SNPRINTF /* Make room for the result. */ if (xsum (count, pad) > allocated - length) { --- 4527,4533 ---- if (w < width) { size_t pad = width - w; ! /* Make room for the result. */ if (xsum (count, pad) > allocated - length) { *************** *** 4533,4544 **** xmax (xsum3 (length, count, pad), xtimes (allocated, 2)); length += count; ENSURE_ALLOCATION (n); length -= count; } /* Here count + pad <= allocated - length. */ ! # endif { # if !DCHAR_IS_TCHAR || USE_SNPRINTF DCHAR_T * const rp = result + length; --- 4537,4552 ---- 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. */ ! { # if !DCHAR_IS_TCHAR || USE_SNPRINTF DCHAR_T * const rp = result + length; *************** *** 4599,4611 **** } #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 --- 4607,4612 ----