1// Copyright 2019 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package runtime 6 7import "unsafe" 8 9func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) { 10 // Check that (*[n]elem)(p) is appropriately aligned. 11 // TODO(mdempsky): What about fieldAlign? 12 if uintptr(p)&(uintptr(elem.align)-1) != 0 { 13 throw("checkptr: unsafe pointer conversion") 14 } 15 16 // Check that (*[n]elem)(p) doesn't straddle multiple heap objects. 17 if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) { 18 throw("checkptr: unsafe pointer conversion") 19 } 20} 21 22func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) { 23 if 0 < uintptr(p) && uintptr(p) < minLegalPointer { 24 throw("checkptr: unsafe pointer arithmetic") 25 } 26 27 // Check that if the computed pointer p points into a heap 28 // object, then one of the original pointers must have pointed 29 // into the same object. 30 base := checkptrBase(p) 31 if base == 0 { 32 return 33 } 34 35 for _, original := range originals { 36 if base == checkptrBase(original) { 37 return 38 } 39 } 40 41 throw("checkptr: unsafe pointer arithmetic") 42} 43 44// checkptrBase returns the base address for the allocation containing 45// the address p. 46// 47// Importantly, if p1 and p2 point into the same variable, then 48// checkptrBase(p1) == checkptrBase(p2). However, the converse/inverse 49// is not necessarily true as allocations can have trailing padding, 50// and multiple variables may be packed into a single allocation. 51func checkptrBase(p unsafe.Pointer) uintptr { 52 // stack 53 if gp := getg(); gp.stack.lo <= uintptr(p) && uintptr(p) < gp.stack.hi { 54 // TODO(mdempsky): Walk the stack to identify the 55 // specific stack frame or even stack object that p 56 // points into. 57 // 58 // In the mean time, use "1" as a pseudo-address to 59 // represent the stack. This is an invalid address on 60 // all platforms, so it's guaranteed to be distinct 61 // from any of the addresses we might return below. 62 return 1 63 } 64 65 // heap (must check after stack because of #35068) 66 if base, _, _ := findObject(uintptr(p), 0, 0); base != 0 { 67 return base 68 } 69 70 // data or bss 71 for _, datap := range activeModules() { 72 if datap.data <= uintptr(p) && uintptr(p) < datap.edata { 73 return datap.data 74 } 75 if datap.bss <= uintptr(p) && uintptr(p) < datap.ebss { 76 return datap.bss 77 } 78 } 79 80 return 0 81} 82