bsdtar core dumps
Sean McNeil
sean at mcneil.com
Tue Aug 24 10:40:22 PDT 2004
On Sat, 2004-08-21 at 10:19, Tim Kientzle wrote:
> Sean McNeil wrote:
> >>>
> >>>I just tried to unarchive a file that didn't exist and got a core dump:
> >
> > Here is a backtrace of the error:
> >
> > #0 0x0000000200926d7e in __vfprintf (fp=0x7fffffffe360,
> > fmt0=0x4161d9 "Failed to open '%s'", ap=0x7fffffffe640)
> > at /usr/src/lib/libc/stdio/vfprintf.c:1052
> > #1 0x00000002008c4006 in vsnprintf (str=0x32 <Address 0x32 out of bounds>,
> > n=4284889, fmt=0x4161d9 "Failed to open '%s'", ap=0x7fffffffe640)
> > at /usr/src/lib/libc/stdio/vsnprintf.c:75
> > #2 0x0000000000411478 in __archive_string_vsprintf (as=0x520240,
> > fmt=0x4161d9 "Failed to open '%s'", ap=0x7fffffffe640)
> > at /usr/src/lib/libarchive/archive_string_sprintf.c:60
> >
> > Could be a compiler bug I suppose, but more likely I think it is this
> > code:
> >
> > if (n == 0) {
> > if (on > 0)
> > *str = '\0';
> > str = dummy;
> > n = 1;
> > }
> >
> > in vsnprintf.c::vsnprintf.
>
> 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. ;-)
>
> Please try the attached patch to libarchive/archive_string_sprintf.c
> and let me know if it works for you. It simply
> forces the target buffer to be allocated and thereby
> avoids calling vsnprintf with a NULL buffer.
>
> Tim Kientzle
>
> ______________________________________________________________________
> Index: archive_string_sprintf.c
> ===================================================================
> RCS file: /home/ncvs/src/lib/libarchive/archive_string_sprintf.c,v
> retrieving revision 1.4
> diff -u -r1.4 archive_string_sprintf.c
> --- archive_string_sprintf.c 14 Aug 2004 03:45:45 -0000 1.4
> +++ archive_string_sprintf.c 21 Aug 2004 17:02:49 -0000
> @@ -48,6 +48,9 @@
> {
> size_t l;
>
> + /* Make sure the target area is initialized. */
> + __archive_string_ensure(as, 64);
> +
> if (fmt == NULL) {
> as->s[0] = 0;
> return;
I think what is happening is that the amd64 architecture passes a
va_list by reference instead of by value. This is causing a side-effect
within __vfprintf. To counter the side-effect, the following patch
saves the ap and uses the copy for the second call to vsnprintf. Here
is a patch that fixes my core dump:
*** lib/libarchive/archive_string_sprintf.c.orig Fri Aug 13
20:45:45 2004--- lib/libarchive/archive_string_sprintf.c Tue Aug 24
10:37:02 2004
*************** __archive_string_vsprintf(struct archive
*** 47,63 ****
va_list ap)
{
size_t l;
if (fmt == NULL) {
as->s[0] = 0;
return;
}
l = vsnprintf(as->s, as->buffer_length, fmt, ap);
/* If output is bigger than the buffer, resize and try again. */
if (l+1 >= as->buffer_length) {
__archive_string_ensure(as, l + 1);
! l = vsnprintf(as->s, as->buffer_length, fmt, ap);
}
as->length = l;
}
--- 47,65 ----
va_list ap)
{
size_t l;
+ va_list ap1;
if (fmt == NULL) {
as->s[0] = 0;
return;
}
+ va_copy(ap1,ap);
l = vsnprintf(as->s, as->buffer_length, fmt, ap);
/* If output is bigger than the buffer, resize and try again. */
if (l+1 >= as->buffer_length) {
__archive_string_ensure(as, l + 1);
! l = vsnprintf(as->s, as->buffer_length, fmt, ap1);
}
as->length = l;
}
More information about the freebsd-current
mailing list