mirror of
https://github.com/golang/go
synced 2024-11-19 18:54:41 -07:00
runtime: resolve type offsets using source module
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>
This commit is contained in:
parent
3f1ed24551
commit
34c480afa8
@ -199,11 +199,11 @@ func (t *_type) nameOff(off nameOff) name {
|
|||||||
return resolveNameOff(unsafe.Pointer(t), off)
|
return resolveNameOff(unsafe.Pointer(t), off)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *_type) typeOff(off typeOff) *_type {
|
func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
|
||||||
if off == 0 {
|
if off == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
base := uintptr(unsafe.Pointer(t))
|
base := uintptr(ptrInModule)
|
||||||
var md *moduledata
|
var md *moduledata
|
||||||
for next := &firstmoduledata; next != nil; next = next.next {
|
for next := &firstmoduledata; next != nil; next = next.next {
|
||||||
if base >= next.types && base < next.etypes {
|
if base >= next.types && base < next.etypes {
|
||||||
@ -235,6 +235,10 @@ func (t *_type) typeOff(off typeOff) *_type {
|
|||||||
return (*_type)(unsafe.Pointer(res))
|
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 {
|
func (t *_type) textOff(off textOff) unsafe.Pointer {
|
||||||
base := uintptr(unsafe.Pointer(t))
|
base := uintptr(unsafe.Pointer(t))
|
||||||
var md *moduledata
|
var md *moduledata
|
||||||
@ -596,15 +600,19 @@ func typesEqual(t, v *_type) bool {
|
|||||||
for i := range it.mhdr {
|
for i := range it.mhdr {
|
||||||
tm := &it.mhdr[i]
|
tm := &it.mhdr[i]
|
||||||
vm := &iv.mhdr[i]
|
vm := &iv.mhdr[i]
|
||||||
tname := it.typ.nameOff(tm.name)
|
// Note the mhdr array can be relocated from
|
||||||
vname := iv.typ.nameOff(vm.name)
|
// another module. See #17724.
|
||||||
|
tname := resolveNameOff(unsafe.Pointer(tm), tm.name)
|
||||||
|
vname := resolveNameOff(unsafe.Pointer(vm), vm.name)
|
||||||
if tname.name() != vname.name() {
|
if tname.name() != vname.name() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if tname.pkgPath() != vname.pkgPath() {
|
if tname.pkgPath() != vname.pkgPath() {
|
||||||
return false
|
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
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user