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