Re: bsdtar core dumps

From: Sean McNeil <sean_at_mcneil.com>
Date: Sun, 22 Aug 2004 18:48:13 -0700
On Sun, 2004-08-22 at 16:34, Giorgos Keramidas wrote:
> On 2004-08-22 15:29, Sean McNeil <sean_at_mcneil.com> wrote:
> > On Sat, 2004-08-21 at 10:19, Tim Kientzle wrote:
> > > The code you've pointed to above concerns me because of the part about:
> > >      if (n == 0) {
> > >            ...
> > >            n = 1;
> > >      }
> > >
> > > That ain't right: If I told vsnprintf the buffer size was zero, it
> > > should treat it as such.  If I meant "one", I would have said "one."
> > >
> > > On the other hand, the vsnprintf.3 man page does explicitly state
> > > that "the output is always null-terminated," which would preclude
> > > passing a zero-length buffer, which is exactly what libarchive is
> > > doing in this situation.  It is bogus, but at least it's documented
> > > bogosity. ;-)
> 
> The vsnprintf() function cannot pass a zero-length buffer to __vfprintf()
> because the __vfprintf() function is expected return the number of bytes it
> would need to do the real printing.  It's not illegal to pass a zero-length
> bugger to vsnprintf(); at least it's not specifically prohibited by the
> manpage.  The following program *DOES* pass zero as the length of the
> buffer to vsnprintf() and a NULL pointer as the buffer address but doesn't
> fault on an i386 machine:
> 
>      1	#include <stdarg.h>
>      2	#include <stdio.h>
>      3
>      4	size_t koko(const char *_fmt, ...);
>      5
>      6	int
>      7	main(void)
>      8	{
>      9		size_t foo;
>     10
>     11		foo = koko("%ld", 5);
>     12		printf("rc = %lu\n", (unsigned long)foo);
>     13		return 0;
>     14	}
>     15
>     16	size_t
>     17	koko(const char *fmt, ...)
>     18	{
>     19		size_t rc;
>     20		va_list ap;
>     21
>     22		va_start(ap, fmt);
>     23		rc = vsnprintf(NULL, 0, fmt, ap);
>     24		va_end(ap);
>     25		return rc;
>     26	}

Yes, I tried this myself and it works just fine.  I think I've found
part of the problem, though:

Breakpoint 1, __archive_string_vsprintf (as=0x520240, fmt=0x4161d9
"Failed to open '%s'", ap=0x7fffffffe5a0) at
/usr/src/lib/libarchive/archive_string_sprintf.c:56
(gdb) print *ap
$24 = {gp_offset = 24, fp_offset = 48, overflow_arg_area =
0x7fffffffe6a0, reg_save_area = 0x7fffffffe5c0}
(gdb) n
(gdb) print *ap
$25 = {gp_offset = 32, fp_offset = 48, overflow_arg_area =
0x7fffffffe6a0, reg_save_area = 0x7fffffffe5c0}

After first call to vsnprintf the va_list has been messed up.  If I
manually set it back to 24 then I get the appropriate message and no
core dump.  So vsnprintf caused ap to be overwritten/incremented from
the args (i.e. the %s) in the format string.  I'd expect it would
increment farther depending on the number of args in the format.

Sean
Received on Sun Aug 22 2004 - 23:48:15 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:07 UTC