Ok, after searching the Net and some newsgroups, I came up with a
compromise solution. Apparently the C standard has recently defined the
va_copy() macro, which can be used to copy a va_list type object. This
means that option 1 (see quote of my previous mail below) can be used.
However, those systems (like mine) that don't have va_copy() will have to
define one manually. So for my system this would mean the following
modifications:
----------------------------------------------------
#ifndef va_copy
#ifdef __WATCOMC__
/* Watcom defines va_list as "typedef char *valist[1]" */
#define va_copy(d, s) (*(d) = *(s))
#endif
#endif /* va_copy */
int vasprintf(char **ptr, const char *format, va_list ap)
{
int ret;
va_list tmp_ap;
va_copy(tmp_ap, ap);
ret = vsnprintf(NULL, 0, format, tmp_ap);
if (ret <= 0) return ret;
(*ptr) = (char *)malloc(ret+1);
if (!*ptr) return -1;
ret = vsnprintf(*ptr, ret+1, format, ap);
return ret;
}
----------------------------------------------------
I tried that and it seems to solve the problem on my system. Note that I
didn't wrap the usage of va_copy in ifdefs, so this will break on systems
that don't have va_copy and didn't define one manually.
Do you think this is an acceptable solution?
regards,
rick
On Wed, 3 Oct 2001, Rick Lake wrote:
> ========================> SAMBA version: 2.2.1a
> OS: QNX4.25
> Compiler: Watcom 10.6
> ========================>
> Hello,
>
> The smbd daemon is crashing under certain conditions. I tracked it down to
> the vasprintf() routine in $srcdir/lib/snprintf.c:
>
> int vasprintf(char **ptr, const char *format, va_list ap)
> {
> int ret;
>
> ret = vsnprintf(NULL, 0, format, ap);
> if (ret <= 0) return ret;
>
> (*ptr) = (char *)malloc(ret+1);
> if (!*ptr) return -1;
> ret = vsnprintf(*ptr, ret+1, format, ap);
>
> return ret;
> }
>
> The problem is that vsnprintf() is called twice with the same 'ap'
> argument. The first call clobbers ap, so when the second call uses it,
> problems occur. I'm not sure if this is the correct behavior in va_list
> processing, but on my system it fails.
>
> Unfortunately I haven't got a quick fix for this yet. Some solution
> options might be:
>
> 1. Somehow save the state of 'ap' so that it can be reused. (This
might
> introduce portability problems, though...)
>
> 2. Somehow pass two instances of ap which point to the same argument list,
> and then use one per call. But I don't see how this can be done without
> changing the usage of vasnprintf() to differ from the standard
> description, which is of course unacceptable. (I tried this with a global
> instance. This worked, but then the calling routine would have to take
> this global into account. :-( )
>
> 3. Calculate the 'ret' value in a different way (i.e. without
calling
> vsnprintf() the first time).
>
> Sorry I couldn't come up with a real fix, but in the mean time I'm
> pondering upon the problem.
>
> regards,
> rick
>
>