]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix GC scanning of slices
authorDmitriy Vyukov <dvyukov@google.com>
Wed, 15 May 2013 19:50:32 +0000 (23:50 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Wed, 15 May 2013 19:50:32 +0000 (23:50 +0400)
If a slice points to an array embedded in a struct,
the whole struct can be incorrectly scanned as the slice buffer.
Fixes #5443.

R=cshapiro, iant, r, cshapiro, minux.ma
CC=bradfitz, gobot, golang-dev
https://golang.org/cl/9372044

src/pkg/runtime/gc_test.go
src/pkg/runtime/mgc0.c

index 26fc77de11f6885eefd3b8fcca121067e04fac80..d40dccb788861b19917631688cfa03b24d5aadc3 100644 (file)
@@ -97,3 +97,27 @@ func TestGcHashmapIndirection(t *testing.T) {
                m[a] = T{}
        }
 }
+
+func TestGcArraySlice(t *testing.T) {
+       type X struct {
+               buf     [1]byte
+               nextbuf []byte
+               next    *X
+       }
+       var head *X
+       for i := 0; i < 10; i++ {
+               p := &X{}
+               p.buf[0] = 42
+               p.next = head
+               if head != nil {
+                       p.nextbuf = head.buf[:]
+               }
+               head = p
+               runtime.GC()
+       }
+       for p := head; p != nil; p = p.next {
+               if p.buf[0] != 42 {
+                       t.Fatal("corrupted heap")
+               }
+       }
+}
index b5f81c7e755523314969a3aa7b87942ec8f1a786..2f26e31c3f45cbb2a41649a4f4e826303da1b8ec 100644 (file)
@@ -799,7 +799,11 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
                        sliceptr = (Slice*)(stack_top.b + pc[1]);
                        if(sliceptr->cap != 0) {
                                obj = sliceptr->array;
-                               objti = pc[2] | PRECISE | LOOP;
+                               // Can't use slice element type for scanning,
+                               // because if it points to an array embedded
+                               // in the beginning of a struct,
+                               // we will scan the whole struct as the slice.
+                               // So just obtain type info from heap.
                        }
                        pc += 3;
                        break;