]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: resolve type offsets using source module
authorDavid Crawshaw <crawshaw@golang.org>
Tue, 1 Nov 2016 19:28:55 +0000 (15:28 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Tue, 1 Nov 2016 20:28:17 +0000 (20:28 +0000)
The runtime.typeEquals function is used during typelinksinit to
determine the canonical set of *_type values to use throughout the
runtime. As such, it is run against non-canonical *_type values, that
is, types from modules that are duplicates of a type from another
module that was loaded earlier in the program life.

These non-canonical *_type values sometimes contain pointers. These
pointers are pointing to position-independent data, and so they are set
by ld.so using dynamic relocations when the module is loaded. As such,
the pointer can point to the equivalent memory from a previous module.

This means if typesEqual follows a pointer inside a *_type, it can end
up at a piece of memory from another module. If it reads a typeOff or
nameOff from that memory and attempts to resolve it against the
non-canonical *_type from the later module, it will end up with a
reference to junk memory.

Instead, resolve against the pointer the offset was read from, so the
data is valid.

Fixes #17709.
Should no longer matter after #17724 is resolved in a later Go.

Change-Id: Ie88b151a3407d82ac030a97b5b6a19fc781901cb
Reviewed-on: https://go-review.googlesource.com/32513
Run-TryBot: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/runtime/type.go

index a3a19b9be03205553423cea01efbba189a2ed423..3ecc54c72c7415ed5d6b72a6cea2d832c52b9f58 100644 (file)
@@ -199,11 +199,11 @@ func (t *_type) nameOff(off nameOff) name {
        return resolveNameOff(unsafe.Pointer(t), off)
 }
 
-func (t *_type) typeOff(off typeOff) *_type {
+func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
        if off == 0 {
                return nil
        }
-       base := uintptr(unsafe.Pointer(t))
+       base := uintptr(ptrInModule)
        var md *moduledata
        for next := &firstmoduledata; next != nil; next = next.next {
                if base >= next.types && base < next.etypes {
@@ -235,6 +235,10 @@ func (t *_type) typeOff(off typeOff) *_type {
        return (*_type)(unsafe.Pointer(res))
 }
 
+func (t *_type) typeOff(off typeOff) *_type {
+       return resolveTypeOff(unsafe.Pointer(t), off)
+}
+
 func (t *_type) textOff(off textOff) unsafe.Pointer {
        base := uintptr(unsafe.Pointer(t))
        var md *moduledata
@@ -596,15 +600,19 @@ func typesEqual(t, v *_type) bool {
                for i := range it.mhdr {
                        tm := &it.mhdr[i]
                        vm := &iv.mhdr[i]
-                       tname := it.typ.nameOff(tm.name)
-                       vname := iv.typ.nameOff(vm.name)
+                       // Note the mhdr array can be relocated from
+                       // another module. See #17724.
+                       tname := resolveNameOff(unsafe.Pointer(tm), tm.name)
+                       vname := resolveNameOff(unsafe.Pointer(vm), vm.name)
                        if tname.name() != vname.name() {
                                return false
                        }
                        if tname.pkgPath() != vname.pkgPath() {
                                return false
                        }
-                       if !typesEqual(it.typ.typeOff(tm.ityp), iv.typ.typeOff(vm.ityp)) {
+                       tityp := resolveTypeOff(unsafe.Pointer(tm), tm.ityp)
+                       vityp := resolveTypeOff(unsafe.Pointer(vm), vm.ityp)
+                       if !typesEqual(tityp, vityp) {
                                return false
                        }
                }