| Summary: | NULL pointer write in vfprintf code | ||
|---|---|---|---|
| Product: | Base System | Reporter: | luddes <luddes> |
| Component: | misc | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
On Wed, Dec 13, 2000 at 05:19:51AM -0800, luddes@hotmail.com wrote: > > >Number: 23521 > >Category: misc > >Synopsis: NULL pointer write in vfprintf code > >Originator: Ludde > >Release: 4.1.1 > >Environment: > FreeBSD matchbox.dumle.nu 4.1.1-RELEASE FreeBSD 4.1.1-RELEASE #3: Wed Dec 6 19:34:33 CET 2000 root@matchbox.dumle.nu:/usr/src/sys/compile/MATCHBOX i386 > >Description: > This code crashes because of a NULL pointer write inside the vfprintf code. > It should print the 8th argument as an integer. > printf("%8$d", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); > > GDB output: > 0x280d49e0 in vfprintf () from /usr/lib/libc.so.4 > (gdb) x/i $eip > 0x280d49e0 <vfprintf+10028>: mov %eax,(%edx) > (gdb) info reg edx > edx 0x0 0 > >How-To-Repeat: > Compile a C program with this contents: > int main() { > printf("%8$d", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); > } > and run it > >Fix: > Perhaps the memory allocation failure is at: > if (tablemax >= STATIC_ARG_TBL_SIZE) { > *argtable = (void **) > malloc (sizeof (void *) * (tablemax + 1)); > } For the record, I can 'reliably' duplicate this. It always happens on %8$ or above; up to 7 works fine. The following test program: #include <stdio.h> int main(void) { printf("%5$d\n", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); printf("%6$d\n", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); printf("%7$d\n", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); printf("%8$d\n", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); /* notreached :( */ return 0; } ..produces the following result: [roam@ringworld:v4 ~/c/misc/foo]$ ./foo 5 6 7 Segmentation fault (core dumped) [roam@ringworld:v4 ~/c/misc/foo]$ ..no matter what combination of -g*, -O* and -f* options I compile it with. I've tested this on RELENG_4 and -current, both as of Dec 11, and the result was identical. G'luck, Peter -- What would this sentence be like if pi were 3? The bug is due to code in __grow_type_table() trashing the stack from calling memset() with the wrong address. The patch below should fix the problem. Note: it was interesting that the original vfprintf() code didn't crash when compiled with just "-g" but "-g -O" crashed it just fine. Mark Index: vfprintf.c =================================================================== RCS file: /cvs/freebsd/src/lib/libc/stdio/vfprintf.c,v retrieving revision 1.22 diff -u -r1.22 vfprintf.c --- vfprintf.c 1999/08/28 00:01:20 1.22 +++ vfprintf.c 2000/12/18 03:50:48 @@ -1191,7 +1191,7 @@ reallocf (typetable, sizeof (unsigned char) * newsize); } - memset (&typetable [*tablesize], T_UNUSED, (newsize - *tablesize)); + memset (*typetable + *tablesize, T_UNUSED, (newsize - *tablesize)); *tablesize = newsize; } State Changed From-To: open->closed Fixed in versions 1.23 (HEAD) and 1.22.2.1 (RELENG_4). |
This code crashes because of a NULL pointer write inside the vfprintf code. It should print the 8th argument as an integer. printf("%8$d", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); GDB output: 0x280d49e0 in vfprintf () from /usr/lib/libc.so.4 (gdb) x/i $eip 0x280d49e0 <vfprintf+10028>: mov %eax,(%edx) (gdb) info reg edx edx 0x0 0 Fix: Perhaps the memory allocation failure is at: if (tablemax >= STATIC_ARG_TBL_SIZE) { *argtable = (void **) malloc (sizeof (void *) * (tablemax + 1)); } How-To-Repeat: Compile a C program with this contents: int main() { printf("%8$d", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } and run it