Re: Breakage (?) in configure and git_vsnprintf()
- From
Jeff King <peff@peff.net>
- Date
- Dec 12, 2011, 14:25 UTC
- Message-ID
- <20111212142550.GA23875@sigill.intra.peff.net>
- In-Reply-To
- <m262hmgmrw.fsf@igel.home>
On Mon, Dec 12, 2011 at 10:30:27AM +0100, Andreas Schwab wrote:
Show 8 quoted lines
> 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; }
-- 1.7.8.13.g74677