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