va_copy() problem
Hello, I see crashes with a string handling library on DragonFly. The problem can be reduced to the test program below. It crashes on DragonFly when compiled with gcc -O2 -o foo foo.c. Without -O2 it runs fine. No problems on Linux with or without -O2. Can anyone spot the problem? I think its related to the use of va_copy(). Thanks, Johannes #include stdio.h #include string.h #include stdlib.h #include stdarg.h struct string { char *str; int size; int len; }; void string_resize(struct string *s, int n) { if (n 0 n s-size) { if (!s-str) { s-str = malloc(n); s-str[0] = '\0'; } else { s-str = realloc(s-str, n); } s-size = n; } } void string_printfa(struct string *s, char *format, ...) { va_list va, va1; int n; va_start(va, format); for (;;) { va_copy(va1, va); n = vsnprintf(s-str + s-len, s-size - s-len, format, va); va_end(va1); if (n s-size - s-len) { s-len += n; break; } string_resize(s, s-len + n + 1); } va_end(va); } int main(int argc, char **argv) { struct string s = {NULL, 0, 0}; string_resize(s, 1); string_printfa(s, %s %s , foo, bar); string_printfa(s, %s %s , foo, bar); printf(%s\n, s.str); return 0; }
gcc update (was: Re: va_copy() problem)
Johannes Hofmann wrote: Hello, I see crashes with a string handling library on DragonFly. The problem can be reduced to the test program below. It crashes on DragonFly when compiled with gcc -O2 -o foo foo.c. Without -O2 it runs fine. No problems on Linux with or without -O2. Can anyone spot the problem? I think its related to the use of va_copy(). No, the problem is that gcc uses %ebx after a function call, which it is not allowed to do: void string_printfa(struct string *s, char *format, ...) { 8048682: 55 push %ebp 8048683: 89 e5 mov%esp,%ebp 8048685: 56 push %esi 8048686: 53 push %ebx 8048687: 83 ec 10sub$0x10,%esp 804868a: 8b 5d 08mov0x8(%ebp),%ebx loads ebx 804868d: 8b 75 0cmov0xc(%ebp),%esi va_list va, va1; int n; va_start(va, format); 8048690: 8d 45 10lea0x10(%ebp),%eax 8048693: 89 45 f4mov%eax,0xfff4(%ebp) for (;;) { va_copy(va1, va); 8048696: 8b 45 f4mov0xfff4(%ebp),%eax 8048699: 89 45 f0mov%eax,0xfff0(%ebp) n = vsnprintf(s-str + s-len, s-size - s-len, format, va1); 804869c: 8b 53 08mov0x8(%ebx),%edx ^^^ uses ebx 804869f: 50 push %eax 80486a0: 56 push %esi 80486a1: 8b 43 04mov0x4(%ebx),%eax 80486a4: 29 d0 sub%edx,%eax 80486a6: 50 push %eax 80486a7: 03 13 add(%ebx),%edx 80486a9: 52 push %edx 80486aa: e8 01 fe ff ff call 80484b0 [EMAIL PROTECTED] call 80486af: 89 c1 mov%eax,%ecx if (n s-size - s-len) { 80486b1: 8b 53 08mov0x8(%ebx),%edx continues using ebx. WRONG. 80486b4: 8b 43 04mov0x4(%ebx),%eax 80486b7: 29 d0 sub%edx,%eax 80486b9: 83 c4 10add$0x10,%esp 80486bc: 39 c1 cmp%eax,%ecx 80486be: 7d 0d jge80486cd string_printfa+0x4b However, gcc34 also has the same bug, so I am at loss here. Or does the ABI dictate that %ebx needs to be restored? Seems that linux/glibc doesn't clobber ebx. cheers simon signature.asc Description: OpenPGP digital signature
Re: va_copy() problem
On Mon, Nov 12, 2007 at 06:58:30PM +, Johannes Hofmann wrote: va_copy(va1, va); n = vsnprintf(s-str + s-len, s-size - s-len, format, va); va_end(va1); va - va1 in the call to vsnprintf. Also consider using vasprintf. Joerg
Re: gcc update (was: Re: va_copy() problem)
On Mon, Nov 12, 2007 at 09:27:17PM +0100, Simon 'corecode' Schubert wrote: No, the problem is that gcc uses %ebx after a function call, which it is not allowed to do: It is allowed to. From the i386 ABI: If necessary, a function saves the values of %edi, %esi, and %ebx in the positions shown and restores their values before returning to the caller. Joerg
vsnprintf broken (was: Re: gcc update)
Simon 'corecode' Schubert wrote: Johannes Hofmann wrote: Hello, I see crashes with a string handling library on DragonFly. The problem can be reduced to the test program below. It crashes on DragonFly when compiled with gcc -O2 -o foo foo.c. Without -O2 it runs fine. No problems on Linux with or without -O2. Can anyone spot the problem? I think its related to the use of va_copy(). No, the problem is that gcc uses %ebx after a function call, which it is not allowed to do: [snip] Or does the ABI dictate that %ebx needs to be restored? Seems that linux/glibc doesn't clobber ebx. okay, I am wrong here. %ebx is supposed to be saved and is also being saved by vsnprinf. gcc is good. So this is actually a case of stack smashing. Have fun finding the bug in vsnprintf or in your code :) cheers simon signature.asc Description: OpenPGP digital signature
Re: va_copy() problem
Joerg Sonnenberger [EMAIL PROTECTED] wrote: On Mon, Nov 12, 2007 at 06:58:30PM +, Johannes Hofmann wrote: va_copy(va1, va); n = vsnprintf(s-str + s-len, s-size - s-len, format, va); va_end(va1); va - va1 in the call to vsnprintf. Also consider using vasprintf. Ooops, you are right of course. But unfortunately it still crashes badly... -stack-protector -fno-stack-protector does not help either. Johannes Joerg