mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-26 01:32:25 +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:
parent
9cea4aaf06
commit
dbb8e96493
36
misc.c
36
misc.c
@ -180,20 +180,11 @@ char *dupcat(const char *s1, ...)
|
|||||||
* Do an sprintf(), but into a custom-allocated buffer.
|
* Do an sprintf(), but into a custom-allocated buffer.
|
||||||
*
|
*
|
||||||
* Currently I'm doing this via vsnprintf. This has worked so far,
|
* Currently I'm doing this via vsnprintf. This has worked so far,
|
||||||
* but it's not good, because:
|
* but it's not good, because vsnprintf is not available on all
|
||||||
*
|
* platforms. There's an ifdef to use `_vsnprintf', which seems
|
||||||
* - vsnprintf is not available on all platforms. There's an ifdef
|
* to be the local name for it on Windows. Other platforms may
|
||||||
* to use `_vsnprintf', which seems to be the local name for it
|
* lack it completely, in which case it'll be time to rewrite
|
||||||
* on Windows. Other platforms may lack it completely, in which
|
* this function in a totally different way.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* The only `properly' portable solution I can think of is to
|
* The only `properly' portable solution I can think of is to
|
||||||
* implement my own format string scanner, which figures out an
|
* implement my own format string scanner, which figures out an
|
||||||
@ -241,7 +232,24 @@ char *dupvprintf(const char *fmt, va_list ap)
|
|||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
#endif
|
#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);
|
len = vsnprintf(buf, size, fmt, ap);
|
||||||
|
#endif
|
||||||
if (len >= 0 && len < size) {
|
if (len >= 0 && len < size) {
|
||||||
/* This is the C99-specified criterion for snprintf to have
|
/* This is the C99-specified criterion for snprintf to have
|
||||||
* been completely successful. */
|
* been completely successful. */
|
||||||
|
Loading…
Reference in New Issue
Block a user