FYI: all tests passed on IRIX (not that I suspected otherwise).
-Brandon
On 12/12/2011 08:25 AM, Jeff King wrote:
Show 69 quoted lines
> On Mon, Dec 12, 2011 at 10:30:27AM +0100, Andreas Schwab wrote:
>
>> Jeff King <peff@peff.net> writes:
>>
>>> if (maxsize > 0) {
>>> - ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
>>> + va_copy(cp, ap);
>>> + ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
>>
>> You also need to call va_end on the copy.
>
> Silly me. Thanks for catching.
>
> Junio, here's a corrected version.
>
> -- >8 --
> Subject: [PATCH] compat/snprintf: don't look at va_list twice
>
> If you define SNPRINTF_RETURNS_BOGUS, we use a special
> git_vsnprintf wrapper assumes that vsnprintf returns "-1"
> instead of the number of characters that you would need to
> store the result.
>
> To do this, it invokes vsnprintf multiple times, growing a
> heap buffer until we have enough space to hold the result.
> However, this means we evaluate the va_list parameter
> multiple times, which is generally a bad thing (it may be
> modified by calls to vsnprintf, yielding undefined
> behavior).
>
> Instead, we must va_copy it and hand the copy to vsnprintf,
> so we always have a pristine va_list.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> compat/snprintf.c | 9 +++++++--
> 1 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/compat/snprintf.c b/compat/snprintf.c
> index e1e0e75..42ea1ac 100644
> --- a/compat/snprintf.c
> +++ b/compat/snprintf.c
> @@ -19,11 +19,14 @@
> #undef vsnprintf
> int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
> {
> + va_list cp;
> char *s;
> int ret = -1;
>
> if (maxsize > 0) {
> - ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
> + va_copy(cp, ap);
> + ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
> + va_end(cp);
> if (ret == maxsize-1)
> ret = -1;
> /* Windows does not NUL-terminate if result fills buffer */
> @@ -42,7 +45,9 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
> if (! str)
> break;
> s = str;
> - ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
> + va_copy(cp, ap);
> + ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
> + va_end(cp);
> if (ret == maxsize-1)
> ret = -1;
> }