danger.go (1684B)
1 package danger 2 3 import ( 4 "fmt" 5 "reflect" 6 "unsafe" 7 ) 8 9 const maxInt = uintptr(int(^uint(0) >> 1)) 10 11 func SubsliceOffset(data []byte, subslice []byte) int { 12 datap := (*reflect.SliceHeader)(unsafe.Pointer(&data)) 13 hlp := (*reflect.SliceHeader)(unsafe.Pointer(&subslice)) 14 15 if hlp.Data < datap.Data { 16 panic(fmt.Errorf("subslice address (%d) is before data address (%d)", hlp.Data, datap.Data)) 17 } 18 offset := hlp.Data - datap.Data 19 20 if offset > maxInt { 21 panic(fmt.Errorf("slice offset larger than int (%d)", offset)) 22 } 23 24 intoffset := int(offset) 25 26 if intoffset > datap.Len { 27 panic(fmt.Errorf("slice offset (%d) is farther than data length (%d)", intoffset, datap.Len)) 28 } 29 30 if intoffset+hlp.Len > datap.Len { 31 panic(fmt.Errorf("slice ends (%d+%d) is farther than data length (%d)", intoffset, hlp.Len, datap.Len)) 32 } 33 34 return intoffset 35 } 36 37 func BytesRange(start []byte, end []byte) []byte { 38 if start == nil || end == nil { 39 panic("cannot call BytesRange with nil") 40 } 41 startp := (*reflect.SliceHeader)(unsafe.Pointer(&start)) 42 endp := (*reflect.SliceHeader)(unsafe.Pointer(&end)) 43 44 if startp.Data > endp.Data { 45 panic(fmt.Errorf("start pointer address (%d) is after end pointer address (%d)", startp.Data, endp.Data)) 46 } 47 48 l := startp.Len 49 endLen := int(endp.Data-startp.Data) + endp.Len 50 if endLen > l { 51 l = endLen 52 } 53 54 if l > startp.Cap { 55 panic(fmt.Errorf("range length is larger than capacity")) 56 } 57 58 return start[:l] 59 } 60 61 func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer { 62 // TODO: replace with unsafe.Add when Go 1.17 is released 63 // https://github.com/golang/go/issues/40481 64 return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset)) 65 }