1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Use va_copy() where available. This should fix a segfault in vsnprintf()

on AMD 64 Linux.
(This has been sitting in my checkout for ages and hasn't obviously caused
any trouble -- I think I was waiting to get round to trying it with VC6, which
I haven't yet. There are some notes in comments on further tweaks that could
be made.)

[originally from svn r7035]
This commit is contained in:
Jacob Nevins 2006-12-29 16:38:52 +00:00
parent 9cea4aaf06
commit dbb8e96493

36
misc.c
View File

@ -180,20 +180,11 @@ char *dupcat(const char *s1, ...)
* Do an sprintf(), but into a custom-allocated buffer.
*
* Currently I'm doing this via vsnprintf. This has worked so far,
* but it's not good, because:
*
* - vsnprintf is not available on all platforms. There's an ifdef
* to use `_vsnprintf', which seems to be the local name for it
* on Windows. Other platforms may lack it completely, in which
* case it'll be time to rewrite this function in a totally
* different way.
*
* - technically you can't reuse a va_list like this: it is left
* unspecified whether advancing a va_list pointer modifies its
* value or something it points to, so on some platforms calling
* vsnprintf twice on the same va_list might fail hideously. It
* would be better to use the `va_copy' macro mandated by C99,
* but that too is not yet ubiquitous.
* but it's not good, because vsnprintf is not available on all
* platforms. There's an ifdef to use `_vsnprintf', which seems
* to be the local name for it on Windows. Other platforms may
* lack it completely, in which case it'll be time to rewrite
* this function in a totally different way.
*
* The only `properly' portable solution I can think of is to
* implement my own format string scanner, which figures out an
@ -241,7 +232,24 @@ char *dupvprintf(const char *fmt, va_list ap)
#ifdef _WINDOWS
#define vsnprintf _vsnprintf
#endif
#ifdef va_copy
/* Use the `va_copy' macro mandated by C99, if present.
* XXX some environments may have this as __va_copy() */
va_list aq;
va_copy(aq, ap);
len = vsnprintf(buf, size, fmt, aq);
va_end(aq);
#else
/* Ugh. No va_copy macro, so do something nasty.
* Technically, you can't reuse a va_list like this: it is left
* unspecified whether advancing a va_list pointer modifies its
* value or something it points to, so on some platforms calling
* vsnprintf twice on the same va_list might fail hideously
* (indeed, it has been observed to).
* XXX the autoconf manual suggests that using memcpy() will give
* "maximum portability". */
len = vsnprintf(buf, size, fmt, ap);
#endif
if (len >= 0 && len < size) {
/* This is the C99-specified criterion for snprintf to have
* been completely successful. */