Re: [PATCH 1/4] stringbuf: A string buffer implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Oct 24, 2007, at 17:21:10, Matthew Wilcox wrote:
On Wed, Oct 24, 2007 at 04:59:48PM -0400, Kyle Moffett wrote:
This seems unlikely to work reliably as the various "v*printf" functions modify the va_list argument they are passed. It may happen to work on your particular architecture depending on how that argument data is passed and stored, but you probably actually want to make a copy of the varargs list for the first vsnprintf call.

I based what I did on how printk works:

        va_start(args, fmt);
        r = vprintk(fmt, args);
        va_end(args);

It doesn't call va_* anywhere else. I don't claim to be a varargs expert, but if I'm wrong, I'm at least wrong the same way that printk is, so not in any way that's significant for any other architecture Linux runs on.

No, the problem is what happens when you don't have enough space allocated: you call "vsnprintf(s, len, format, args);" and then later call "vsprintf(s, format, args);" with the *SAME* "args". That's what's broken.

So this is wrong:
va_list args;
va_start(args, fmt);
r1 = vprintk(fmt, args);
r2 = vprintk(fmt, args);
va_end(args);

To fix it, you have 2 options.

Option 1:
va_list args;
va_start(args, fmt);
r1 = vprintk(fmt, args);
va_end(args);
va_start(args, fmt);
r2 = vprintk(fmt, args);
va_end(args);

Option 2:
va_list args, argscopy;
va_start(args, fmt);
va_copy(argscopy, args);
r1 = vprintk(fmt, argscopy);
va_end(argscopy);
r2 = vprintk(fmt, args);
va_end(args);

Now in a function which *receives* a va_list from one of its callers, "Option 1" isn't an option because you don't have the original stack frame, so the result looks like this:

void func1(const char *fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	func2(fmt, ap);
	va_end(ap);
}

void func2(const char *fmt, va_list ap)
{
	va_list ap2;
	va_copy(ap2, ap);
	vprintk(fmt, ap2);
	va_end(ap2);
	vprintk(fmt, ap);
}

Cheers,
Kyle Moffett

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux