260
|
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 |
} |