// Copyright 2020 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package state import ( "fmt" "reflect" "runtime" "unsafe" ) // reflectValueRWAddr is equivalent to obj.Addr(), except that the returned // reflect.Value is usable in assignments even if obj was obtained by the use // of unexported struct fields. // // Preconditions: obj.CanAddr(). func reflectValueRWAddr(obj reflect.Value) reflect.Value { return reflect.NewAt(obj.Type(), unsafe.Pointer(obj.UnsafeAddr())) } // reflectValueRWSlice3 is equivalent to arr.Slice3(i, j, k), except that the // returned reflect.Value is usable in assignments even if obj was obtained by // the use of unexported struct fields. // // Preconditions: // * arr.Kind() == reflect.Array. // * i, j, k >= 0. // * i <= j <= k <= arr.Len(). func reflectValueRWSlice3(arr reflect.Value, i, j, k int) reflect.Value { if arr.Kind() != reflect.Array { panic(fmt.Sprintf("arr has kind %v, wanted %v", arr.Kind(), reflect.Array)) } if i < 0 || j < 0 || k < 0 { panic(fmt.Sprintf("negative subscripts (%d, %d, %d)", i, j, k)) } if i > j { panic(fmt.Sprintf("subscript i (%d) > j (%d)", i, j)) } if j > k { panic(fmt.Sprintf("subscript j (%d) > k (%d)", j, k)) } if k > arr.Len() { panic(fmt.Sprintf("subscript k (%d) > array length (%d)", k, arr.Len())) } sliceTyp := reflect.SliceOf(arr.Type().Elem()) if i == arr.Len() { // By precondition, i == j == k == arr.Len(). return reflect.MakeSlice(sliceTyp, 0, 0) } slh := reflect.SliceHeader{ // reflect.Value.CanAddr() == false for arrays, so we need to get the // address from the first element of the array. Data: arr.Index(i).UnsafeAddr(), Len: j - i, Cap: k - i, } slobj := reflect.NewAt(sliceTyp, unsafe.Pointer(&slh)).Elem() // Before slobj is constructed, arr holds the only pointer-typed pointer to // the array since reflect.SliceHeader.Data is a uintptr, so arr must be // kept alive. runtime.KeepAlive(arr) return slobj }