Skip to content

runtime: use of large map key causes crash #3573

Closed

Description

@remyoudompheng
What steps will reproduce the problem?
1. go run this program:

package main

type Big [50]int64

func main() {
    seen := make(map[Big]bool)
    pow := Big{0: 2}
    for b := 0; b < 100; b++ {
        seen[pow] = true
    }
}

What is the expected output? What do you see instead?

Expected: nothing.
Got:
$ go run crash.go
panic: invalid memory address or nil pointer dereference
throw: panic during gc
[signal 0xb code=0x1 addr=0x0 pc=0x404ada]

goroutine 1 [running]:
main.main()
    /tmp/crash.go:9 +0xa6

goroutine 2 [syscall]:
created by runtime.main
    /build/src/release-build/src/pkg/runtime/proc.c:221
exit status 2

GDB trace:
(gdb) run
Starting program: /tmp/crash 
[New LWP 15165]

Program received signal SIGSEGV, Segmentation fault.
[Switching to LWP 15165]
ReleaseN (c=void, l=void, n=void, sizeclass=void) at
/opt/remy/go/src/pkg/runtime/mcache.c:63
63          lp = &(*lp)->next;
(gdb) bt
#0  ReleaseN (c=void, l=void, n=void, sizeclass=void) at
/opt/remy/go/src/pkg/runtime/mcache.c:63
#1  0x0000000000404cdb in runtime.MCache_ReleaseAll (c=void) at
/opt/remy/go/src/pkg/runtime/mcache.c:126
#2  0x0000000000407465 in stealcache () at /opt/remy/go/src/pkg/runtime/mgc0.c:882
#3  0x0000000000407869 in runtime.gc (force=void) at
/opt/remy/go/src/pkg/runtime/mgc0.c:998
#4  0x000000000040fea3 in runtime.mallocgc (size=void, flag=void, dogc=void,
zeroed=void) at /opt/remy/go/src/pkg/runtime/malloc.goc:97
#5  0x0000000000410aa5 in runtime.mal (n=void) at
/opt/remy/go/src/pkg/runtime/malloc.goc:432
#6  0x000000000040244f in hash_subtable_new (h=void, power=void, used=void) at
/opt/remy/go/src/pkg/runtime/hashmap.c:73
#7  0x0000000000402dad in hash_grow (t=void, h=void, pst=void, flags=void) at
/opt/remy/go/src/pkg/runtime/hashmap.c:240

I use linux/amd64.
Happens with go1 as well as tip (go version weekly.2012-03-27 +d9a1980f5814)

Activity

  1. remyoudompheng commented on Apr 28, 2012

    @remyoudompheng
    ContributorAuthor

    Comment 1:

    Owner changed to ---.

  2. robpike commented on Apr 28, 2012

    @robpike
    Contributor

    Comment 2:

    Fails on Mac too.

    Labels changed: added priority-asap, removed priority-triage.

    Owner changed to @dvyukov.

    Status changed to Accepted.

  3. ianlancetaylor commented on Apr 29, 2012

    @ianlancetaylor
    Contributor

    Comment 3:

    It's a straighforward but very serious bug.  The hashmap code uses a uint8 to store the
    size of a data element.  That means that the hashmap code fails if the total of the key
    size plus the data size, with appropriate rounding, is >= 256.  That was fine before Go
    1, but it failed once we started to permit struct and array values to be used as hash
    keys.
    But strangely there is already an assertion to check for this type of error in hash_init:
        assert (h->datasize == datasize);
    Ah, but it doesn't work because the caller uses h->valoff, which is itself a uint8 field.
    Here is a possible fix but I'm not sure it's ideal or complete:
    http://golang.org/cl/6137051

    Owner changed to ---.

  4. ianlancetaylor commented on Apr 30, 2012

    @ianlancetaylor
    Contributor

    Comment 4:

    Labels changed: added go1.0.2.

  5. rsc commented on May 25, 2012

    @rsc
    Contributor

    Comment 5:

    This issue was closed by revision bf18d57.

    Status changed to Fixed.

  6. kortschak commented on Jun 2, 2012

    @kortschak
    Contributor

    Comment 6:

    This appears not to be fixed at tip.
    $ go tool 6g -V
    6g version weekly.2012-03-27 +d8e47164f8dd
    The following code demonstrates a variety of errors:
    package main
    import "fmt"
    const id = "scaf" // or var id = "scaf" or other values - see comments below
    type sf struct {
        id string
        i  int
    }
    type sp struct {
        a, b sf
    }
    func main() {
        seen := map[sp]struct{}{}
        for i := 0; i < 500; i++ {
            fmt.Println(i)
            a := sf{id, i}
            aa := sp{a, a}
            seen[aa] = struct{}{}
        }
    }
    The results depend on the value of and 'type' of id:
    if it's const "" then the result is always a `throw: hashmap assert`, if it's a var ""
    then it's either that or `invalid memory address or nil pointer dereference`
    if it's const or var "a" then mainly `unexpected fault address`, but sometime `hashmap
    assert'
    if it's const or var "scaf", sometimes it hangs and sometimes it throws `hashmap assert`
    - other '4-words' behave differently (id ~< "naaa" behaves like "a", id ~> "naaa"
    behaves like "scaf" - not exhaustively confirmed for all values)
    The common thing is that the throw or hang always happens as i == 81.
    Removing the integer or the string field results in normal behaviour.
  7. rsc commented on Jun 14, 2012

    @rsc
    Contributor

    Comment 8:

    Note that the problem reported in comment 6 became issue #3695, now fixed.
  8. added this to the Go1.0.2 milestone on Apr 14, 2015
  9. added a commit that references this issue on May 11, 2015
    dfb1149
  10. locked and limited conversation to collaborators on Jun 24, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions