github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/state/decode_unsafe.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package state 16 17 import ( 18 "fmt" 19 "reflect" 20 "runtime" 21 "unsafe" 22 ) 23 24 // reflectValueRWAddr is equivalent to obj.Addr(), except that the returned 25 // reflect.Value is usable in assignments even if obj was obtained by the use 26 // of unexported struct fields. 27 // 28 // Preconditions: obj.CanAddr(). 29 func reflectValueRWAddr(obj reflect.Value) reflect.Value { 30 return reflect.NewAt(obj.Type(), unsafe.Pointer(obj.UnsafeAddr())) 31 } 32 33 // reflectValueRWSlice3 is equivalent to arr.Slice3(i, j, k), except that the 34 // returned reflect.Value is usable in assignments even if obj was obtained by 35 // the use of unexported struct fields. 36 // 37 // Preconditions: 38 // - arr.Kind() == reflect.Array. 39 // - i, j, k >= 0. 40 // - i <= j <= k <= arr.Len(). 41 func reflectValueRWSlice3(arr reflect.Value, i, j, k int) reflect.Value { 42 if arr.Kind() != reflect.Array { 43 panic(fmt.Sprintf("arr has kind %v, wanted %v", arr.Kind(), reflect.Array)) 44 } 45 if i < 0 || j < 0 || k < 0 { 46 panic(fmt.Sprintf("negative subscripts (%d, %d, %d)", i, j, k)) 47 } 48 if i > j { 49 panic(fmt.Sprintf("subscript i (%d) > j (%d)", i, j)) 50 } 51 if j > k { 52 panic(fmt.Sprintf("subscript j (%d) > k (%d)", j, k)) 53 } 54 if k > arr.Len() { 55 panic(fmt.Sprintf("subscript k (%d) > array length (%d)", k, arr.Len())) 56 } 57 58 sliceTyp := reflect.SliceOf(arr.Type().Elem()) 59 if i == arr.Len() { 60 // By precondition, i == j == k == arr.Len(). 61 return reflect.MakeSlice(sliceTyp, 0, 0) 62 } 63 slh := reflect.SliceHeader{ 64 // reflect.Value.CanAddr() == false for arrays, so we need to get the 65 // address from the first element of the array. 66 Data: arr.Index(i).UnsafeAddr(), 67 Len: j - i, 68 Cap: k - i, 69 } 70 slobj := reflect.NewAt(sliceTyp, unsafe.Pointer(&slh)).Elem() 71 // Before slobj is constructed, arr holds the only pointer-typed pointer to 72 // the array since reflect.SliceHeader.Data is a uintptr, so arr must be 73 // kept alive. 74 runtime.KeepAlive(arr) 75 return slobj 76 }