github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/runtime/checkptr.go (about)

     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  package runtime
     6  
     7  import "github.com/x04/go/src/unsafe"
     8  
     9  func 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  
    22  func 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.
    51  func 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  }