va_copy() problem

2007-11-12 Thread Johannes Hofmann
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)

2007-11-12 Thread Simon 'corecode' Schubert
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

2007-11-12 Thread Joerg Sonnenberger
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)

2007-11-12 Thread Joerg Sonnenberger
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)

2007-11-12 Thread Simon 'corecode' Schubert
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

2007-11-12 Thread Johannes Hofmann
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