Re: RedHat Linux 6.0 warning: stack corruption with "g++ -O2" and"pow()"

From: Matthew D. Langston (langston@SLAC.stanford.edu)
Date: Wed Jun 30 1999 - 17:37:55 MEST


Hi Damir

Damir Buskulic wrote:
> 
> It's very nice you warn us. Could you be more specific, please. I'm
> using -O2 on LinuxPPC R5 which is the equivalent of RedHat6.0 for
> Macs.  What is the exact problem, and could you give a simple script
> that shows it, so I can try and see if it happens also on my mnachine?

I am cross posting to the roottalk list in case others may want to test
their systems for this bug as well.

I have attached the files which I included in my original bug report to
the egcs developers.

To test if you might have the bug, then compile "test.cxx" with
"g++ -O2".  On my system this will create a program that will cause a
core dump at run time due to a signal 11, Segmentation fault.

If you inspect the program with gdb (making sure to specify the core
file), and if you know Intel assembly (see the file test.s for the full,
but tiny, assembler listing) then it will be obvious where the problem
is (pow's exponent is being used as a register offset).

--
Matthew D. Langston
SLD, Stanford Linear Accelerator Center
langston@SLAC.Stanford.EDU


# -*- Makefile -*-

VPATH        = /mnt/hdc/projects/ROOT/2.00/root-bug/src
CC           = g++
CXX          = g++
CXXFLAGS     = -g -O2 -Wall

.PHONY: check clean
check: test
	./test

clean:
	rm -f test core a.out *.o *~

%.o: %.cxx
	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@


egcs 1.1.2 bug: stack corruption with "pow" and "-O2"

I have found that g++ from egcs 1.1.2 produces bad assembly code when
the "pow" function from glibc 2.1 is inlined (via the "-O2" optimization
flag) in the same stack frame as a trivial C++ object which has a user
defined default constructor and copy constructor.

The following code reproduces this problem on my system:

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                             begin example
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#include <cmath>

class Foo
{
      Foo( const Foo& );
   public:      
      Foo() {}
};


int main()
{
   Foo foo;

   double m = pow( 1.0, 1.0 );
   m = pow( m, 1.0 );
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                              end example
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Compiling this example on my system using "g++ -O2" will create a
program that will cause a core dump at run time due to a signal 11,
Segmentation fault.

The interesting thing about this bug is that commenting out the private
copy constructor makes the bug disappear.

My system configuration is:

  Machine configuration with bug
  ------------------------------
  RedHat Linux 6.0 Intel
  kernel 2.2.5
  glibc 2.1.1
  egcs 1.1.2
  binutils 2.9.1.0.23

Here is the command line, and its output, used to create `test.ii'
(which is attached below):

langston@seto$ g++ -v --save-temps -O2 test.cxx 
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/cpp -lang-c++ -v -undef -D__GNUC__=2 -D__GNUG__=2 -D__cplusplus -D__GNUC_MINOR__=91 -D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -D__ELF__ -D__unix__ -D__i386__ -D__i386__ -D__linux__ -D__unix -D__i386 -D__linux -Asystem(posix) -D__EXCEPTIONS -D__OPTIMIZE__ -Asystem(unix) -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ test.cxx test.ii
GNU CPP version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) (i386 Linux/ELF)
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/g++-2
 /usr/i386-redhat-linux/include
 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include
 /usr/include
End of search list.
 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/cc1plus test.ii -quiet -dumpbase test.cc -O2 -version -o test.s
GNU C++ version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) (i386-redhat-linux) compiled by GNU C version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release).
 as -V -Qy -o test.o test.s
GNU assembler version 2.9.1 (i386-redhat-linux), using BFD version 2.9.1.0.23
 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtbegin.o -L/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66 -L/usr/i386-redhat-linux/lib test.o -lstdc++ -lm -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtend.o /usr/lib/crtn.o
langston@seto$ 

--
Matthew D. Langston
SLD, Stanford Linear Accelerator Center
langston@SLAC.Stanford.EDU


#include <cmath>

class Foo
{
      Foo( const Foo& );
   public:      
      Foo() {}
};


int main()
{
   Foo foo;

   double m = pow( 1.0, 1.0 );
   m = pow( m, 1.0 );
}



.file "test.cxx" .version "01.01" gcc2_compiled.: .section .rodata .align 8 .LC46: .long 0x0,0x3ff00000 .align 16 .LC47: .long 0x0,0x80000000,0x3fff .text .align 4 .globl main .type main,@function main: .LFB1: pushl %ebp .LCFI0: movl %esp,%ebp .LCFI1: subl $36,%esp .LCFI2: pushl %edi .LCFI3: pushl %esi .LCFI4: pushl %ebx .LCFI5: leal -4(%ebp),%ebx fld1 fld %st(0) fnstcw -4(%ebx) movl -4(%ebx),%eax movb $12,%ah movl %eax,-12(%ebx) fldcw -12(%ebx) fistpll -12(%ebx) movl -12(%ebx),%esi movl -8(%ebx),%edi fldcw -4(%ebx) pushl %edi pushl %esi fildll (%esp) addl $8,%esp fucomp %st(1) fnstsw %ax andb $68,%ah xorb $64,%ah jne .L326 fld1 movl %esi,%eax orl %edi,%eax jne .L327 fstp %st(0) jmp .L325 .p2align 4,,7 .L327: testl %edi,%edi jge .L332 negl %esi adcl $0,%edi negl %edi jmp .L332 .L352: fxch %st(1) .p2align 4,,7 .L332: testl $1,%esi je .L333 fld %st(1) fmulp %st,%st(1) .L333: shrdl $1,%edi,%esi sarl $1,%edi movl %esi,%eax orl %edi,%eax je .L354 fxch %st(1) fmul %st(0),%st jmp .L352 .p2align 4,,7 .L326: fldl .LC46 fxch %st(1) #APP fyl2x #NO_APP fstpt -36(%ebp) fldt -36(%ebp) fldl .LC46 #APP fmul %st(1) # y * log2(x) fst %st(1) frndint # int(y * log2(x)) fxch fsub %st(1) # fract(y * log2(x)) f2xm1 # 2^(fract(y * log2(x))) - 1 #NO_APP fldt .LC47 faddp %st,%st(1) #APP fscale #NO_APP .L354: fstp %st(1) subl $8,%esp fstpl (%esp) popl %eax popl %edx movl %eax,-24(%ebp) movl %edx,-20(%ebp) fldl -24(%ebp) .L325: fld1 fld %st(0) fnstcw -4(%ebx) movl -4(%ebx),%edx movb $12,%dh movl %edx,-12(%ebx) fldcw -12(%ebx) fistpll -12(%ebx) movl -12(%ebx),%ebx movl -8(%ebx),%esi fldcw -4(%ebx) fldz fucomp %st(2) fnstsw %ax andb $69,%ah cmpb $64,%ah je .L353 pushl %esi pushl %ebx fildll (%esp) addl $8,%esp fucompp fnstsw %ax andb $68,%ah xorb $64,%ah jne .L338 fstp %st(0) movl %ebx,%eax orl %esi,%eax je .L337 testl %esi,%esi jge .L344 negl %ebx adcl $0,%esi negl %esi .p2align 4,,7 .L344: shrdl $1,%esi,%ebx sarl $1,%esi movl %ebx,%eax orl %esi,%eax je .L337 jmp .L344 .p2align 4,,7 .L338: fldl .LC46 fxch %st(1) #APP fyl2x #NO_APP fstpt -36(%ebp) fldt -36(%ebp) fldl .LC46 #APP fmul %st(1) # y * log2(x) fst %st(1) frndint # int(y * log2(x)) fxch fsub %st(1) # fract(y * log2(x)) f2xm1 # 2^(fract(y * log2(x))) - 1 #NO_APP fldt .LC47 faddp %st,%st(1) #APP fscale #NO_APP .L353: fstp %st(0) fstp %st(0) .L337: xorl %eax,%eax leal -48(%ebp),%esp popl %ebx popl %esi popl %edi leave ret .LFE1: .Lfe1: .size main,.Lfe1-main .section .eh_frame,"aw",@progbits __FRAME_BEGIN__: .4byte .LLCIE1 .LSCIE1: .4byte 0x0 .byte 0x1 .byte 0x0 .byte 0x1 .byte 0x7c .byte 0x8 .byte 0xc .byte 0x4 .byte 0x4 .byte 0x88 .byte 0x1 .align 4 .LECIE1: .set .LLCIE1,.LECIE1-.LSCIE1 .4byte .LLFDE1 .LSFDE1: .4byte .LSFDE1-__FRAME_BEGIN__ .4byte .LFB1 .4byte .LFE1-.LFB1 .byte 0x4 .4byte .LCFI0-.LFB1 .byte 0xe .byte 0x8 .byte 0x85 .byte 0x2 .byte 0x4 .4byte .LCFI1-.LCFI0 .byte 0xd .byte 0x5 .byte 0x4 .4byte .LCFI3-.LCFI1 .byte 0x87 .byte 0xc .byte 0x4 .4byte .LCFI4-.LCFI3 .byte 0x86 .byte 0xd .byte 0x4 .4byte .LCFI5-.LCFI4 .byte 0x83 .byte 0xe .align 4 .LEFDE1: .set .LLFDE1,.LEFDE1-.LSFDE1 .ident "GCC: (GNU) egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)"



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:35 MET