vasprintf() bug. [fix proposal]

Rick Lake rick at anp.nl
Fri Oct 19 08:57:05 GMT 2001


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
>
>






More information about the samba mailing list