[Bug c/13757] New: -fstack-check can crash Hello World

gcc-bugzilla at gcc dot gnu dot org gcc-bugzilla@gcc.gnu.org
Tue Jan 20 04:30:00 GMT 2004


The -fstack-check compiler option emits code which can make any program
segfault on entering its mainline.
The placement of the stack relative to page boundaries needs to be right
to demonstrate the problem.
This placement varies with environment, length of pathname used to invoke the
program, whether it is invoked directly or via GDB,
and quite possibly other factors also.
This is an old problem, I first saw it at gcc 2.95.3.
Shell/expect scripts in How-To-Repeat demonstrate the problem reliably.

This is a dissasem of main() :-

0x8048354 <main>:       push   %ebp
0x8048355 <main+1>:     mov    %esp,%ebp
0x8048357 <main+3>:     sub    $0x18,%esp
0x804835a <main+6>:     and    $0xfffffff0,%esp
0x804835d <main+9>:     movl   $0x0,0xfffffffc(%ebp)
0x8048364 <main+16>:    lea    0xffffded8(%esp,1),%eax
0x804836b <main+23>:    mov    %eax,0xfffffff8(%ebp)
0x804836e <main+26>:    mov    0xfffffffc(%ebp),%eax
0x8048371 <main+29>:    add    $0x1128,%eax
0x8048376 <main+34>:    mov    %esp,%edx
0x8048378 <main+36>:    sub    %eax,%edx
0x804837a <main+38>:    mov    %edx,0xfffffff4(%ebp)
0x804837d <main+41>:    jmp    0x804838f <main+59>
0x804837f <main+43>:    mov    0xfffffff8(%ebp),%eax
0x8048382 <main+46>:    movl   $0x0,(%eax)
0x8048388 <main+52>:    subl   $0x1000,0xfffffff8(%ebp)
0x804838f <main+59>:    mov    0xfffffff4(%ebp),%edx
0x8048392 <main+62>:    cmp    %edx,0xfffffff8(%ebp)
0x8048395 <main+65>:    ja     0x804837f <main+43>
0x8048397 <main+67>:    mov    0xfffffff4(%ebp),%eax
0x804839a <main+70>:    movl   $0x0,(%eax)
0x80483a0 <main+76>:    sub    0xfffffffc(%ebp),%esp
0x80483a3 <main+79>:    lea    0xffffeed8(%esp,1),%eax
0x80483aa <main+86>:    movl   $0x0,(%eax)
0x80483b0 <main+92>:    movl   $0x8048424,(%esp,1)
0x80483b7 <main+99>:    call   0x8048278 <printf>
0x80483bc <main+104>:   mov    $0x0,%eax
0x80483c1 <main+109>:   leave  
0x80483c2 <main+110>:   ret    

The segfault occurs at 0x804839a <main+70>:    movl   $0x0,(%eax)

Environment:
System: Linux dimstar 2.4.24 #1 Sat Jan 10 17:03:52 EST 2004 i686 unknown
Architecture: i686

	
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: /usr/src/gcc-3.3.2/configure --prefix=/usr/local/gcc3.2

How-To-Repeat:
The preprocessed source:-

---------------------------- START hello.i ----------------------------
extern int printf (__const char *__restrict __format, ...) ;
int main(int argc,char**argv)
{
        printf("\nHello World!\n\n");
        return 0 ;
}
---------------------------- END hello.i ----------------------------

This test script will verify that we get the crash.
It works by increasing the length of the pathname of hello
in 16 byte increnents until it crashes (copious output) :- 

---------------------------- START sh.sh ----------------------------
#!/bin/sh
gcc -g -Wall -fstack-check -o hello hello.i
i=aaaaaaaaaaaaaaa
j=`/bin/pwd`
while(true);do
$j/hello || break
j=$j/$i
mkdir -p $j
cp hello $j
done
echo "Failing path is $j"
---------------------------- END sh.sh ----------------------------

This script discovers the required pathname to see the problem under gdb.
It saves this in the command file "cmd" for future use :-

---------------------------- START demo.sh ----------------------------
#!/bin/sh
# expect treats all the shell lines as comment comtinuations \
gcc -g -Wall -fstack-check -o hello hello.i; \
i=aaaaaaaaaaaaaaa; \
exec expect -f "$0" -- $i `/bin/pwd`

# We need to find a path that shows the problem when run under gdb

set i [lindex $argv 0]
set j [lindex $argv 1]

puts "Finding a pathname that displays the problem."
puts "This may take a while..."
log_user 0

spawn sh
expect "$ "
set k 0
set l 0
while {1} \
{
  puts -nonewline "$l\r"
  flush stdout
  set l [incr l]
  exp_send "gdb $j/hello\r"
  expect "(gdb) "
  exp_send "run\r"
  expect \
  {
    signal \
    {
      set k 1
      expect "(gdb) "
      exp_send "q\r"
      expect "(y or n) "
      exp_send "y\r"
    }
    normally \
    {
      expect "(gdb) "
      exp_send "q\r"
    }
  }
  expect "$ "
  if {$k} break
  set j $j/$i
  exec mkdir -p $j
  exec cp hello $j
}
puts "\nFailing path is $j"
exec echo "gdb $j/hello" > cmd
exec chmod a+x cmd
puts "gdb invocation command stored in ./cmd"
---------------------------- END demo.sh ----------------------------

After running demo.sh, you can invoke gdb by running cmd directly.
Alternatively, you can run the following script to get directly to
the first machine instruction in main() :-

---------------------------- START run_gdb.sh ----------------------------
#!/bin/sh
# expect treats all the shell lines as comment comtinuations \
exec expect -f "$0"
spawn ./cmd
expect "(gdb) "
exp_send "b __libc_start_main\r"
expect "(gdb) "
exp_send "run\r"
expect "(gdb) "
exp_send "n 11\r"
expect "(gdb) "
exp_send "si 10\r"
expect "(gdb) "
puts "\n\nYou can now interact with gdb."
puts "If it won't exit for you (lost LWP or whatever), type \"////\" to kill it"
exp_send " \r"
interact //// exit
---------------------------- END run_gdb.sh ----------------------------

At gcc3.2.2, you can use "si 17" to get to the actual failing instruction.
At that point if you note the contents of eax and use "x" to examine that
location, the program will continue without failing.

Otherwise, 'movl   $0x0,(%eax)' will fail.
I do not understand why this should be.
------- Additional Comments From duncan_roe at acslink dot net dot au  2004-01-20 04:29 -------
Fix:
Workaround: don't use -fstack-check

-- 
           Summary: -fstack-check can crash Hello World
           Product: gcc
           Version: 3.3.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: duncan_roe at acslink dot net dot au
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i686-pc-linux-gnu
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13757



More information about the Gcc-bugs mailing list