Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to pass a va_list to another function without using va_copy?

This blog post claims that passing a va_list to another function like in the following code is unsafe, and that the va_list must first be copied using va_copy:

void
foo_ap(const char *fmt, va_list ap)
{
    char buf[128];

    vsnprintf(buf, sizeof(buf), fmt, ap);

    // now, do something with buf ...
}

Like one of the comments to the blog post mentions, I can't see how this would be unsafe, as the C99 spec states (7.15):

The object ap may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.

(As long as foo_ap doesn't reference ap after passing it on, the second part of the sentence doesn't seem to apply anyway.) The author of the blog post says in another comment that he might be wrong, but maybe someone can add some clarification. Do I really have to use va_copy to be on the safe side? Or are there any platforms that don't conform to the spec and require the use of va_copy?

like image 695
nwellnhof Avatar asked Nov 16 '14 03:11

nwellnhof


1 Answers

You only need va_copy if you still plan to use ap after vsnprintf returns. For example, you might want to call vsnprintf twice - once to determine the required buffer size, and again to format for real. If you don't need to use ap again (except perhaps for passing it to va_end, if you were the one creating it with va_start), then you don't need to va_copy it.

like image 151
Igor Tandetnik Avatar answered Oct 12 '22 02:10

Igor Tandetnik