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