github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/pkg/marshal/primitive/primitive.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 primitive defines marshal.Marshallable implementations for primitive 16 // types. 17 package primitive 18 19 import ( 20 "io" 21 22 "github.com/ttpreport/gvisor-ligolo/pkg/hostarch" 23 "github.com/ttpreport/gvisor-ligolo/pkg/marshal" 24 ) 25 26 // Int8 is a marshal.Marshallable implementation for int8. 27 // 28 // +marshal boundCheck slice:Int8Slice:inner 29 type Int8 int8 30 31 // Uint8 is a marshal.Marshallable implementation for uint8. 32 // 33 // +marshal boundCheck slice:Uint8Slice:inner 34 type Uint8 uint8 35 36 // Int16 is a marshal.Marshallable implementation for int16. 37 // 38 // +marshal boundCheck slice:Int16Slice:inner 39 type Int16 int16 40 41 // Uint16 is a marshal.Marshallable implementation for uint16. 42 // 43 // +marshal boundCheck slice:Uint16Slice:inner 44 type Uint16 uint16 45 46 // Int32 is a marshal.Marshallable implementation for int32. 47 // 48 // +marshal boundCheck slice:Int32Slice:inner 49 type Int32 int32 50 51 // Uint32 is a marshal.Marshallable implementation for uint32. 52 // 53 // +marshal boundCheck slice:Uint32Slice:inner 54 type Uint32 uint32 55 56 // Int64 is a marshal.Marshallable implementation for int64. 57 // 58 // +marshal boundCheck slice:Int64Slice:inner 59 type Int64 int64 60 61 // Uint64 is a marshal.Marshallable implementation for uint64. 62 // 63 // +marshal boundCheck slice:Uint64Slice:inner 64 type Uint64 uint64 65 66 // ByteSlice is a marshal.Marshallable implementation for []byte. 67 // This is a convenience wrapper around a dynamically sized type, and can't be 68 // embedded in other marshallable types because it breaks assumptions made by 69 // go-marshal internals. It violates the "no dynamically-sized types" 70 // constraint of the go-marshal library. 71 type ByteSlice []byte 72 73 // SizeBytes implements marshal.Marshallable.SizeBytes. 74 func (b *ByteSlice) SizeBytes() int { 75 return len(*b) 76 } 77 78 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 79 func (b *ByteSlice) MarshalBytes(dst []byte) []byte { 80 return dst[copy(dst, *b):] 81 } 82 83 // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes. 84 func (b *ByteSlice) UnmarshalBytes(src []byte) []byte { 85 return src[copy(*b, src):] 86 } 87 88 // Packed implements marshal.Marshallable.Packed. 89 func (b *ByteSlice) Packed() bool { 90 return false 91 } 92 93 // MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe. 94 func (b *ByteSlice) MarshalUnsafe(dst []byte) []byte { 95 return b.MarshalBytes(dst) 96 } 97 98 // UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe. 99 func (b *ByteSlice) UnmarshalUnsafe(src []byte) []byte { 100 return b.UnmarshalBytes(src) 101 } 102 103 // CopyIn implements marshal.Marshallable.CopyIn. 104 func (b *ByteSlice) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) { 105 return cc.CopyInBytes(addr, *b) 106 } 107 108 // CopyOut implements marshal.Marshallable.CopyOut. 109 func (b *ByteSlice) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) { 110 return cc.CopyOutBytes(addr, *b) 111 } 112 113 // CopyOutN implements marshal.Marshallable.CopyOutN. 114 func (b *ByteSlice) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) { 115 return cc.CopyOutBytes(addr, (*b)[:limit]) 116 } 117 118 // WriteTo implements io.WriterTo.WriteTo. 119 func (b *ByteSlice) WriteTo(w io.Writer) (int64, error) { 120 n, err := w.Write(*b) 121 return int64(n), err 122 } 123 124 var _ marshal.Marshallable = (*ByteSlice)(nil) 125 126 // The following set of functions are convenient shorthands for wrapping a 127 // built-in type in a marshallable primitive type. For example: 128 // 129 // func useMarshallable(m marshal.Marshallable) { ... } 130 // 131 // // Compare: 132 // 133 // buf = []byte{...} 134 // // useMarshallable(&primitive.ByteSlice(buf)) // Not allowed, can't address temp value. 135 // bufP := primitive.ByteSlice(buf) 136 // useMarshallable(&bufP) 137 // 138 // // Vs: 139 // 140 // useMarshallable(AsByteSlice(buf)) 141 // 142 // Note that the argument to these function escapes, so avoid using them on very 143 // hot code paths. But generally if a function accepts an interface as an 144 // argument, the argument escapes anyways. 145 146 // AllocateInt8 returns x as a marshallable. 147 func AllocateInt8(x int8) marshal.Marshallable { 148 p := Int8(x) 149 return &p 150 } 151 152 // AllocateUint8 returns x as a marshallable. 153 func AllocateUint8(x uint8) marshal.Marshallable { 154 p := Uint8(x) 155 return &p 156 } 157 158 // AllocateInt16 returns x as a marshallable. 159 func AllocateInt16(x int16) marshal.Marshallable { 160 p := Int16(x) 161 return &p 162 } 163 164 // AllocateUint16 returns x as a marshallable. 165 func AllocateUint16(x uint16) marshal.Marshallable { 166 p := Uint16(x) 167 return &p 168 } 169 170 // AllocateInt32 returns x as a marshallable. 171 func AllocateInt32(x int32) marshal.Marshallable { 172 p := Int32(x) 173 return &p 174 } 175 176 // AllocateUint32 returns x as a marshallable. 177 func AllocateUint32(x uint32) marshal.Marshallable { 178 p := Uint32(x) 179 return &p 180 } 181 182 // AllocateInt64 returns x as a marshallable. 183 func AllocateInt64(x int64) marshal.Marshallable { 184 p := Int64(x) 185 return &p 186 } 187 188 // AllocateUint64 returns x as a marshallable. 189 func AllocateUint64(x uint64) marshal.Marshallable { 190 p := Uint64(x) 191 return &p 192 } 193 194 // AsByteSlice returns b as a marshallable. Note that this allocates a new slice 195 // header, but does not copy the slice contents. 196 func AsByteSlice(b []byte) marshal.Marshallable { 197 bs := ByteSlice(b) 198 return &bs 199 } 200 201 // Below, we define some convenience functions for marshalling primitive types 202 // using the newtypes above, without requiring superfluous casts. 203 204 // 8-bit integers 205 206 // CopyInt8In is a convenient wrapper for copying in an int8 from the task's 207 // memory. 208 func CopyInt8In(cc marshal.CopyContext, addr hostarch.Addr, dst *int8) (int, error) { 209 var buf Int8 210 n, err := buf.CopyIn(cc, addr) 211 if err != nil { 212 return n, err 213 } 214 *dst = int8(buf) 215 return n, nil 216 } 217 218 // CopyInt8Out is a convenient wrapper for copying out an int8 to the task's 219 // memory. 220 func CopyInt8Out(cc marshal.CopyContext, addr hostarch.Addr, src int8) (int, error) { 221 srcP := Int8(src) 222 return srcP.CopyOut(cc, addr) 223 } 224 225 // CopyUint8In is a convenient wrapper for copying in a uint8 from the task's 226 // memory. 227 func CopyUint8In(cc marshal.CopyContext, addr hostarch.Addr, dst *uint8) (int, error) { 228 var buf Uint8 229 n, err := buf.CopyIn(cc, addr) 230 if err != nil { 231 return n, err 232 } 233 *dst = uint8(buf) 234 return n, nil 235 } 236 237 // CopyUint8Out is a convenient wrapper for copying out a uint8 to the task's 238 // memory. 239 func CopyUint8Out(cc marshal.CopyContext, addr hostarch.Addr, src uint8) (int, error) { 240 srcP := Uint8(src) 241 return srcP.CopyOut(cc, addr) 242 } 243 244 // 16-bit integers 245 246 // CopyInt16In is a convenient wrapper for copying in an int16 from the task's 247 // memory. 248 func CopyInt16In(cc marshal.CopyContext, addr hostarch.Addr, dst *int16) (int, error) { 249 var buf Int16 250 n, err := buf.CopyIn(cc, addr) 251 if err != nil { 252 return n, err 253 } 254 *dst = int16(buf) 255 return n, nil 256 } 257 258 // CopyInt16Out is a convenient wrapper for copying out an int16 to the task's 259 // memory. 260 func CopyInt16Out(cc marshal.CopyContext, addr hostarch.Addr, src int16) (int, error) { 261 srcP := Int16(src) 262 return srcP.CopyOut(cc, addr) 263 } 264 265 // CopyUint16In is a convenient wrapper for copying in a uint16 from the task's 266 // memory. 267 func CopyUint16In(cc marshal.CopyContext, addr hostarch.Addr, dst *uint16) (int, error) { 268 var buf Uint16 269 n, err := buf.CopyIn(cc, addr) 270 if err != nil { 271 return n, err 272 } 273 *dst = uint16(buf) 274 return n, nil 275 } 276 277 // CopyUint16Out is a convenient wrapper for copying out a uint16 to the task's 278 // memory. 279 func CopyUint16Out(cc marshal.CopyContext, addr hostarch.Addr, src uint16) (int, error) { 280 srcP := Uint16(src) 281 return srcP.CopyOut(cc, addr) 282 } 283 284 // 32-bit integers 285 286 // CopyInt32In is a convenient wrapper for copying in an int32 from the task's 287 // memory. 288 func CopyInt32In(cc marshal.CopyContext, addr hostarch.Addr, dst *int32) (int, error) { 289 var buf Int32 290 n, err := buf.CopyIn(cc, addr) 291 if err != nil { 292 return n, err 293 } 294 *dst = int32(buf) 295 return n, nil 296 } 297 298 // CopyInt32Out is a convenient wrapper for copying out an int32 to the task's 299 // memory. 300 func CopyInt32Out(cc marshal.CopyContext, addr hostarch.Addr, src int32) (int, error) { 301 srcP := Int32(src) 302 return srcP.CopyOut(cc, addr) 303 } 304 305 // CopyUint32In is a convenient wrapper for copying in a uint32 from the task's 306 // memory. 307 func CopyUint32In(cc marshal.CopyContext, addr hostarch.Addr, dst *uint32) (int, error) { 308 var buf Uint32 309 n, err := buf.CopyIn(cc, addr) 310 if err != nil { 311 return n, err 312 } 313 *dst = uint32(buf) 314 return n, nil 315 } 316 317 // CopyUint32Out is a convenient wrapper for copying out a uint32 to the task's 318 // memory. 319 func CopyUint32Out(cc marshal.CopyContext, addr hostarch.Addr, src uint32) (int, error) { 320 srcP := Uint32(src) 321 return srcP.CopyOut(cc, addr) 322 } 323 324 // 64-bit integers 325 326 // CopyInt64In is a convenient wrapper for copying in an int64 from the task's 327 // memory. 328 func CopyInt64In(cc marshal.CopyContext, addr hostarch.Addr, dst *int64) (int, error) { 329 var buf Int64 330 n, err := buf.CopyIn(cc, addr) 331 if err != nil { 332 return n, err 333 } 334 *dst = int64(buf) 335 return n, nil 336 } 337 338 // CopyInt64Out is a convenient wrapper for copying out an int64 to the task's 339 // memory. 340 func CopyInt64Out(cc marshal.CopyContext, addr hostarch.Addr, src int64) (int, error) { 341 srcP := Int64(src) 342 return srcP.CopyOut(cc, addr) 343 } 344 345 // CopyUint64In is a convenient wrapper for copying in a uint64 from the task's 346 // memory. 347 func CopyUint64In(cc marshal.CopyContext, addr hostarch.Addr, dst *uint64) (int, error) { 348 var buf Uint64 349 n, err := buf.CopyIn(cc, addr) 350 if err != nil { 351 return n, err 352 } 353 *dst = uint64(buf) 354 return n, nil 355 } 356 357 // CopyUint64Out is a convenient wrapper for copying out a uint64 to the task's 358 // memory. 359 func CopyUint64Out(cc marshal.CopyContext, addr hostarch.Addr, src uint64) (int, error) { 360 srcP := Uint64(src) 361 return srcP.CopyOut(cc, addr) 362 } 363 364 // CopyByteSliceIn is a convenient wrapper for copying in a []byte from the 365 // task's memory. 366 func CopyByteSliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst *[]byte) (int, error) { 367 var buf ByteSlice 368 n, err := buf.CopyIn(cc, addr) 369 if err != nil { 370 return n, err 371 } 372 *dst = []byte(buf) 373 return n, nil 374 } 375 376 // CopyByteSliceOut is a convenient wrapper for copying out a []byte to the 377 // task's memory. 378 func CopyByteSliceOut(cc marshal.CopyContext, addr hostarch.Addr, src []byte) (int, error) { 379 srcP := ByteSlice(src) 380 return srcP.CopyOut(cc, addr) 381 } 382 383 // CopyStringIn is a convenient wrapper for copying in a string from the 384 // task's memory. 385 func CopyStringIn(cc marshal.CopyContext, addr hostarch.Addr, dst *string) (int, error) { 386 var buf ByteSlice 387 n, err := buf.CopyIn(cc, addr) 388 if err != nil { 389 return n, err 390 } 391 *dst = string(buf) 392 return n, nil 393 } 394 395 // CopyStringOut is a convenient wrapper for copying out a string to the task's 396 // memory. 397 func CopyStringOut(cc marshal.CopyContext, addr hostarch.Addr, src string) (int, error) { 398 srcP := ByteSlice(src) 399 return srcP.CopyOut(cc, addr) 400 }