Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gccgo: double free or corruption #3186

Closed
alberts opened this issue Mar 4, 2012 · 23 comments
Closed

gccgo: double free or corruption #3186

alberts opened this issue Mar 4, 2012 · 23 comments

Comments

@alberts
Copy link
Contributor

alberts commented Mar 4, 2012

What steps will reproduce the problem?

fuzzing again. Not quite sure which file triggered this, because although the warning
was printed, I don't think it changed the exit code of gccgo, so my framework didn't
keep the input file.

If there isn't enough info in this warning, I'll try to obtain another input file that
produces this issue.

What do you see instead?

*** glibc detected *** /opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1: double free
or corruption (out): 0x0000000003005c50 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7dda6)[0x7fb40828cda6]
/lib64/libc.so.6(+0x7f08e)[0x7fb40828e08e]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1(_ZNSt3tr110_HashtableIPK4TypeSt4pairIKS3_P5BtypeESaIS8_ESt10_Select1stIS8_E14Type_identical19Type_hash_identicalNS_8__detail18_Mod_range_hashingENSE_20_Default_ranged_hashENSE_20_Prime_rehash_policyELb0ELb0ELb1EED1Ev+0x39)[0x545679]
/lib64/libc.so.6(+0x39931)[0x7fb408248931]
/lib64/libc.so.6(+0x399b5)[0x7fb4082489b5]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1[0xc3c95f]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1(internal_error+0xc0)[0xc3d390]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1[0xc3c444]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1[0x4ec493]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1(toplev_main+0xa68)[0x7a2408]
/lib64/libc.so.6(__libc_start_main+0xed)[0x7fb40823069d]
/opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1[0x4bace9]

Which compiler are you using (5g, 6g, 8g, gccgo)?

gccgo

Which operating system are you using?

linux

Which revision are you using?  (hg identify)

tip

Please provide any additional information below.

Compiled with

CFLAGS='-O2 -g -Wall -fexceptions -fstack-protector --param=ssp-buffer-size=4
-mtune=generic'
CXXFLAGS='-O2 -g -fexceptions -fstack-protector --param=ssp-buffer-size=4 -mtune=generic'

on Fedora 15 x86_64, which are close to the flags used for all packages in that
distribution. I think they currently use:

-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
--param=ssp-buffer-size=4  -m64 -mtune=generic

so I'll test with that compile set too.
@alberts
Copy link
Contributor Author

alberts commented Mar 4, 2012

Comment 1:

Configured with
../gccgo/configure --prefix=$prefix --mandir=$prefix/share/man
--infodir=$prefix/share/info --disable-bootstrap --enable-shared --enable-threads=posix
--enable-checking=release --disable-build-with-cxx --disable-build-poststage1-with-cxx
--with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
--enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu
--enable-languages=go,lto --enable-plugin --enable-initfini-array --disable-dssi
--with-ppl --with-cloog --with-tune=generic --with-arch_32=i686
--build=x86_64-redhat-linux

@dsymonds
Copy link
Contributor

dsymonds commented Mar 4, 2012

Comment 2:

I don't know if there's enough information there, but an input file that can trigger
this would be immensely useful.

Labels changed: added priority-go1, gccgo, removed priority-triage.

Owner changed to @ianlancetaylor.

Status changed to WaitingForReply.

@alberts
Copy link
Contributor Author

alberts commented Mar 4, 2012

Comment 3:

I've managed to reproduce it a few times. I'll have an input file soon.

@alberts
Copy link
Contributor Author

alberts commented Mar 5, 2012

Comment 4:

triggered another one... still trying to reproduce the original. at least my script is
working now.
*** glibc detected *** /opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1: corrupted
double-linked list: 0x000000000201bd10 ***
LIBC_FATAL_STDERR_=1 gccgo -c 0.go 1.go
built with the following options on Fedora 15 x86_64:
CFLAGS='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
--param=ssp-buffer-size=4 -m64 -mtune=generic'
CXXFLAGS='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
--param=ssp-buffer-size=4 -m64 -mtune=generic'
../gccgo/configure --prefix=$prefix --mandir=$prefix/share/man
--infodir=$prefix/share/info --disable-bootstrap --enable-shared --enable-threads=posix
--enable-checking=release --disable-build-with-cxx --disable-build-poststage1-with-cxx
--with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
--enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu
--enable-languages=c,c++,go,lto --enable-plugin --enable-initfini-array --disable-dssi
--with-ppl --with-cloog --with-tune=generic --with-arch_32=i686
--build=x86_64-redhat-linux

Attachments:

  1. 0.go (859 bytes)
  2. 1.go (2862 bytes)
  3. fuzzgc.py (1789 bytes)

@alberts
Copy link
Contributor Author

alberts commented Mar 5, 2012

Comment 5:

MALLOC_CHECK_=1 LIBC_FATAL_STDERR_=1 gccgo -c -O2 -pipe 0.go
this sometimes triggers:
*** glibc detected *** /opt/gccgo/libexec/gcc/x86_64-redhat-linux/4.8.0/go1: free():
invalid pointer: 0x0000000002595c70 ***

Attachments:

  1. 0.go (3811 bytes)

@alberts
Copy link
Contributor Author

alberts commented Mar 5, 2012

Comment 6:

infinite loop...

Attachments:

  1. 5.go (16494 bytes)
  2. 7.go (9705 bytes)

@remyoudompheng
Copy link
Contributor

Comment 7:

I couldn't reproduce all of them.
I managed to reduce failures to:
package main
type A struct{}
type B struct {
      *C
      *A
} 
and
package p
type Node struct {
      *s
      Parent *Node
}
Same backtrace in both cases.
Program received signal SIGSEGV, Segmentation fault.
Gogo::write_globals (this=0x1573c60) at ../../gccgo/gcc/go/gofrontend/gogo-tree.cc:2442
2442    }
(gdb) bt
#0  Gogo::write_globals (this=0x1573c60) at
../../gccgo/gcc/go/gofrontend/gogo-tree.cc:2442
#1  0x00000000008a109a in compile_file () at ../../gccgo/gcc/toplev.c:573
#2  do_compile () at ../../gccgo/gcc/toplev.c:1938
#3  toplev_main (argc=2, argv=0x7fffffffe518) at ../../gccgo/gcc/toplev.c:2014
#4  0x00007ffff6e8638d in __libc_start_main () from /lib/libc.so.6
#5  0x00000000004cd8b1 in _start ()
(gdb)

@ianlancetaylor
Copy link
Contributor

Comment 8:

Thanks for reducing the test cases.  I just committed a patch that fixes the problem for
the reduced test case.  I haven't tried the others yet.

Status changed to Started.

@alberts
Copy link
Contributor Author

alberts commented Mar 8, 2012

Comment 9:

not sure which ones you couldn't reproduce. infinite loop and double free reproduced
always for me. free(): invalid pointer reproduces about once every 3-4 runs.

@remyoudompheng
Copy link
Contributor

Comment 10:

Oh, I forgot you had to put both files in the compiler. 0.go+1.go, 0.go works fine with
latest gccgo. For 5.go+7.go, the infinite loop triggers on:
package p
const (
      f, g = g, f
      s   := 0
)
func A() {
      return []byte(s)
}

@alberts
Copy link
Contributor Author

alberts commented Mar 10, 2012

Comment 11:

I've run out of crash bugs, so I've had resort to Valgrinding. I'll make a comment for
each set of files and error.
valgrind -v --trace-children=yes gccgo -c *.go
Conditional jump or move depends on uninitialised value(s)
at 0x516D50: Parse::if_stat() (parse.cc:3992)
by 0x5172AC: Parse::statement(Label*) (parse.cc:3364)
by 0x51734D: Parse::statement_list() (parse.cc:3642)
by 0x517B01: Parse::block() (parse.cc:1123)
by 0x516DEB: Parse::if_stat() (parse.cc:4013)
by 0x5172AC: Parse::statement(Label*) (parse.cc:3364)
by 0x51734D: Parse::statement_list() (parse.cc:3642)
by 0x517B01: Parse::block() (parse.cc:1123)
by 0x516DEB: Parse::if_stat() (parse.cc:4013)
by 0x5172AC: Parse::statement(Label*) (parse.cc:3364)
by 0x51734D: Parse::statement_list() (parse.cc:3642)
by 0x517B01: Parse::block() (parse.cc:1123)

Attachments:

  1. 0.go (9653 bytes)

@alberts
Copy link
Contributor Author

alberts commented Mar 10, 2012

Comment 12:

Invalid read of size 8
   at 0x4D8607: Builtin_call_expression::do_check_types(Gogo*) (expressions.cc:14451)
   by 0x4EDAE3: Check_types_traverse::expression(Expression**) (expressions.h:572)
   by 0x4C5565: Expression::traverse(Expression**, Traverse*) (expressions.cc:112)
   by 0x4EFFFD: Block::traverse(Traverse*) (gogo.cc:3601)
   by 0x4F02CE: Function::traverse(Traverse*) (gogo.cc:3222)
   by 0x4F201A: Bindings::traverse(Traverse*, bool) (gogo.cc:5078)
   by 0x4F2271: Gogo::traverse(Traverse*) (gogo.cc:1283)
   by 0x4F3682: Gogo::check_types() (gogo.cc:1869)
   by 0x4E6E90: go_parse_input_files (go.cc:120)
   by 0x7A3FDB: toplev_main (toplev.c:557)
   by 0x68BC69C: (below main) (in /lib64/libc-2.14.90.so)
 Address 0x20 is not stack'd, malloc'd or (recently) free'd

Attachments:

  1. 1.go (23307 bytes)
  2. 2.go (273 bytes)

@alberts
Copy link
Contributor Author

alberts commented Mar 12, 2012

Comment 13:

1 errors in context 1 of 1:
Invalid read of size 2
   at 0x656815: fold (fold-const.c:14069)
   by 0x8ED86A: save_expr (tree.c:2728)
   by 0x4D1D66: Call_expression::set_results(Translate_context*, tree_node*) (expressions.cc:10211)
   by 0x4D309C: Call_expression::do_get_tree(Translate_context*) (expressions.cc:10160)
   by 0x51C319: Expression_statement::do_get_backend(Translate_context*) (statements.cc:1748)
   by 0x4F68EF: Block::get_backend(Translate_context*) (gogo.cc:3675)
   by 0x4E7B53: Variable::get_init_block(Gogo*, Named_object*, tree_node*) (gogo-tree.cc:1181)
   by 0x4EC576: Gogo::write_globals() (gogo-tree.cc:869)
   by 0x7A4027: toplev_main (toplev.c:573)
   by 0x68BC69C: (below main) (in /lib64/libc-2.14.90.so)
 Address 0x0 is not stack'd, malloc'd or (recently) free'd

Attachments:

  1. 0.go (9373 bytes)
  2. 2.go (737 bytes)

@remyoudompheng
Copy link
Contributor

Comment 14:

For the first valgrind report: saw_send_stmt at parse.cc:3974 is uninitialised.
It could be true and trigger a completely weird message
"send statement used as value; use select for non-blocking send"
not sure what is the reason of that message.
Minimal example:
package p
func F() {
      if true || x, y := 1, 2 {
      }
}

@remyoudompheng
Copy link
Contributor

Comment 15:

0.go+2.go is a real segfault for me, and it crashes on a valid source file:
package main
func bar() {
      _ = b
}
func foo() (int, int) {
      return 1, 2
}     
      
var a, b = foo()

@remyoudompheng
Copy link
Contributor

Comment 16:

1.go+2.go is also a real segfault. It happens on:
package p
func F() {
      var s string
      s = append(s, "hello world")
}

@remyoudompheng
Copy link
Contributor

Comment 17:

I sent a patch for review fixing the cases reported in comments 14 (if with an
assignment in the middle) and 16 (append with a string as first argument).
http://golang.org/cl/5848047

@remyoudompheng
Copy link
Contributor

Comment 18:

The example
package main
func bar() int {
      return b
}
func foo() (int, int) {
      return 1, 2
}     
      
var a, b = foo()
fails at the point of the below stacktrace. The error disappears when var a, b ... is
moved above foo() declaration.
Temporary_statement::get_backend_variable (this=0x15f4010, context=0x7fffffffe190)
    at ../../gccgo/gcc/go/gofrontend/statements.cc:467
467 {
(gdb) 
468   if (this->bvariable_ == NULL)
(gdb) 
470       go_assert(saw_errors());
(gdb) bt
#0  Temporary_statement::get_backend_variable (this=0x15f4010, context=0x7fffffffe190)
    at ../../gccgo/gcc/go/gofrontend/statements.cc:470
#1  0x00000000004d65f2 in Temporary_reference_expression::do_get_tree (this=0x15f8780,
context=0x7fffffffe190)
    at ../../gccgo/gcc/go/gofrontend/expressions.cc:1106
#2  0x00000000004ebbc3 in Call_expression::set_results (this=0x15f3560,
context=0x7fffffffe190, call_tree=0x7ffff6a9b9d8)
    at ../../gccgo/gcc/go/gofrontend/expressions.cc:10200
#3  0x00000000004ed81d in do_get_tree (context=<optimized out>, this=0x15f3560)
    at ../../gccgo/gcc/go/gofrontend/expressions.cc:10162
#4  Call_expression::do_get_tree (this=0x15f3560, context=<optimized out>)
    at ../../gccgo/gcc/go/gofrontend/expressions.cc:9989
#5  0x000000000053a78a in Expression_statement::do_get_backend (this=<optimized
out>, context=0x7fffffffe190)
    at ../../gccgo/gcc/go/gofrontend/statements.cc:1748
#6  0x000000000051311c in Block::get_backend (this=0x15f4360, context=0x7fffffffe240)
    at ../../gccgo/gcc/go/gofrontend/gogo.cc:3675
#7  0x0000000000501be1 in Variable::get_init_block (this=0x15f3520, gogo=<optimized
out>, function=<optimized out>, 
    var_decl=0x7ffff6a6f820) at ../../gccgo/gcc/go/gofrontend/gogo-tree.cc:1181
#8  0x00000000005086bf in Gogo::write_globals (this=0x157bc70) at
../../gccgo/gcc/go/gofrontend/gogo-tree.cc:869
#9  0x00000000008a37aa in compile_file () at ../../gccgo/gcc/toplev.c:573
#10 do_compile () at ../../gccgo/gcc/toplev.c:1937
#11 toplev_main (argc=2, argv=0x7fffffffe528) at ../../gccgo/gcc/toplev.c:2013
#12 0x00007ffff6e8638d in __libc_start_main () from /lib/libc.so.6
#13 0x00000000004cddf1 in _start ()

@ianlancetaylor
Copy link
Contributor

Comment 19:

Labels changed: added priority-later, removed priority-go1.

@remyoudompheng
Copy link
Contributor

Comment 20:

I've tackled the case from comment no.10
http://golang.org/cl/5972048/
package p
const (
      f, g = g, f
      s   := 0
)
func A() {
      return []byte(s)
}
actually reducible to
package p
const f, g = g, f
func A() []byte { return []byte(f) }

@remyoudompheng
Copy link
Contributor

Comment 21:

Ah, I think I've understood the problem with 
package main
func foo(int) (int, int)
var c = b
var a, b = foo(0)
In the lowering phase, b is hit first: that triggers the lowering of the call expression
and inserts the call temporaries in b->preinit instead of a->preinit. Then the init()
function gets confused and crashes.
This will compile fine:
  var c = a
  var a, b = foo(0)
This also:
  var a, b = foo(0)
  var c = b

@ianlancetaylor
Copy link
Contributor

Comment 22:

I think I've gone through every test case in this bug report, including running valgrind
myself.  As far as I can tell there is only one remaining failure, the one Rémy
analyzes in comment #21.

@ianlancetaylor
Copy link
Contributor

Comment 23:

I just committed a patch for the last remaining problem, so closing this bug report. 
Let's open a new bug report for further compiler crashes.
Thanks for finding these test cases, and for reducing them.

Status changed to Fixed.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants