github.com/google/capslock@v0.2.3-0.20240517042941-dac19fc347c0/testpkgs/usereflect/usereflect.go (about) 1 // Copyright 2023 Google LLC 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file or at 5 // https://developers.google.com/open-source/licenses/bsd 6 7 // Package usereflect is used for testing. 8 package usereflect 9 10 import ( 11 "encoding/json" 12 "math/rand" 13 "reflect" 14 "sync" 15 "unsafe" 16 17 "github.com/google/capslock/testpkgs/callnet" 18 ) 19 20 // ValueSetFunc uses (reflect.Value).Set to change a func variable 21 // to point to a different function, then calls it. 22 func ValueSetFunc() int { 23 f := func() int { return 42 } 24 v1 := reflect.ValueOf(&f) 25 v2 := v1.Elem() 26 v3 := reflect.ValueOf(callnet.Foo) 27 v2.Set(v3) 28 return f() 29 } 30 31 // ValueSetInt uses (reflect.Value).Set to change an int. 32 func ValueSetInt() int { 33 f := 123 34 g := 456 35 reflect.ValueOf(&f).Elem().Set(reflect.ValueOf(g)) 36 return f 37 } 38 39 type fooer interface { 40 foo() int 41 } 42 43 type t1 int 44 45 func (_ t1) foo() int { return 42 } 46 47 type t2 int 48 49 func (_ t2) foo() int { return callnet.Foo() + 1 } 50 51 // ValueSetInterface uses (reflect.Value).Set to change an interface 52 // variable to a value with a different concrete type. 53 func ValueSetInterface() int { 54 var f fooer = t1(1) 55 var g fooer = t2(1) 56 reflect.ValueOf(&f).Elem().Set(reflect.ValueOf(g)) 57 return f.foo() 58 } 59 60 // MakeFunc sets a func variable to an interesting function using MakeFunc and 61 // (reflect.Value).Set. 62 func MakeFunc() int { 63 f1 := func() int { return 42 } 64 f2 := func(_ []reflect.Value) []reflect.Value { 65 x := callnet.Foo() + 1 66 return []reflect.Value{reflect.ValueOf(x)} 67 } 68 v := reflect.MakeFunc(reflect.ValueOf(f1).Type(), f2) 69 reflect.ValueOf(&f1).Elem().Set(v) 70 return f1() 71 } 72 73 // TypeConfusionWithNewAt modifies a func pointer using reflect.NewAt and 74 // (reflect.Value).Set. 75 func TypeConfusionWithNewAt() int { 76 f := func() int { return 42 } 77 g := func() int { return callnet.Foo() + 1 } 78 fp := &f 79 v := reflect.NewAt(reflect.TypeOf(uintptr(0)), unsafe.Pointer(&fp)).Elem() 80 // v now has type uintptr, but refers to fp. 81 v.Set(reflect.ValueOf(uintptr(unsafe.Pointer(&g)))) 82 return (*fp)() 83 } 84 85 // TypeConfusionWithNewAtTwo modifies a func pointer using reflect.NewAt and 86 // (reflect.Value).Interface. 87 func TypeConfusionWithNewAtTwo() int { 88 f := func() int { return 42 } 89 g := func() int { return callnet.Foo() + 1 } 90 fp := &f 91 v := reflect.NewAt(reflect.TypeOf(uintptr(0)), unsafe.Pointer(&fp)).Interface() 92 *v.(*uintptr) = uintptr(unsafe.Pointer(&g)) 93 return (*fp)() 94 } 95 96 // TypeConfusionWithValueRace uses concurrent writes to a reflect.Value to 97 // create a Value that refers to a func pointer but which has type uintptr. 98 func TypeConfusionWithValueRace() int { 99 var ( 100 fn = func() int { return 42 } 101 goal = callnet.Foo 102 fnp *func() int = &fn 103 u uintptr = 12345 104 done = false 105 ) 106 for !done { 107 // v will contain reflect.Value variables each of which has type 108 // *uintptr or **func() int, pointing to u or fnp respectively. 109 // We start two goroutines which copy these values from one to another, 110 // trying to create a torn reflect.Value that has type *uintptr but which 111 // points to fnp. Then we can write any uintptr to that Value using Set, 112 // making *fnp point to an arbitrary function (in this case, callnet.Foo). 113 var v [100]reflect.Value 114 for i := 0; i < 100; i = i + 2 { 115 v[i], v[i+1] = reflect.ValueOf(&u), reflect.ValueOf(&fnp) 116 } 117 var wg sync.WaitGroup 118 wg.Add(2) 119 go func() { 120 for i := 0; i < 1e7; i++ { 121 v[i%100] = v[(i+1)%100] 122 } 123 wg.Done() 124 }() 125 go func() { 126 for i := 0; i < 1e7; i++ { 127 v[i%100] = v[(i+12)%100] 128 } 129 wg.Done() 130 }() 131 wg.Wait() 132 for i := 0; i < 100; i++ { 133 v := v[i].Elem() 134 if v.Kind() != reflect.Uintptr { 135 continue 136 } 137 if v.Uint() == 12345 { 138 continue 139 } 140 done = true 141 v.SetUint(uint64(uintptr(unsafe.Pointer(&goal)))) 142 } 143 } 144 return (*fnp)() 145 } 146 147 // ChangeSliceCapacityWithSliceHeader uses reflect.SliceHeader to directly 148 // modify the capacity of a slice, in order to overwrite a func pointer. 149 func ChangeSliceCapacityWithSliceHeader() int { 150 var ( 151 fn = func() int { return 42 } 152 goal = callnet.Foo 153 a = make([]uintptr, 1) 154 b = make([]*func() int, 1) 155 ah = (*reflect.SliceHeader)(unsafe.Pointer(&a)) 156 bh = (*reflect.SliceHeader)(unsafe.Pointer(&b)) 157 ) 158 for bh.Data < ah.Data { 159 if rand.Intn(2) == 0 { 160 a = make([]uintptr, 1) 161 } else { 162 b = make([]*func() int, 1) 163 } 164 } 165 n := (bh.Data - ah.Data) / unsafe.Sizeof(a[0]) 166 ah.Cap = int(n + 1) 167 ah.Len = int(n + 1) 168 b[0] = &fn 169 a[n] = uintptr(unsafe.Pointer(&goal)) 170 return (*b[0])() 171 } 172 173 // ReadValue reads a number from a value using reflect. 174 func ReadValue(x any) int { 175 v := reflect.ValueOf(x) 176 switch { 177 case v.CanUint(): 178 return int(v.Uint()) 179 case v.CanInt(): 180 return int(v.Int()) 181 case v.CanFloat(): 182 return int(v.Float()) 183 } 184 return 0 185 } 186 187 // JSONUnmarshal uses encoding/json to decode into a plain int. 188 func JSONUnmarshal() int { 189 var x int 190 json.Unmarshal([]byte("42"), &x) 191 return x 192 } 193 194 type u int 195 196 func (x *u) UnmarshalJSON([]byte) error { 197 *x = u(callnet.Foo() + 1) 198 return nil 199 } 200 201 // JSONUnmarshalTwo uses encoding/json to decode into a type that has 202 // custom Unmarshal code. 203 func JSONUnmarshalTwo() int { 204 var u u 205 json.Unmarshal([]byte("42"), &u) 206 return int(u) 207 } 208 209 var ( 210 f func() int 211 g uintptr 212 globalValue1 = reflect.ValueOf(f) 213 globalValue2 = reflect.ValueOf(g) 214 globalValueStruct1 = rvs{42, reflect.ValueOf(f), 42} 215 globalValueStruct2 = rvs{42, reflect.ValueOf(g), 42} 216 valueSlice1 = []reflect.Value{reflect.ValueOf(f)} 217 valueSlice2 = []reflect.Value{reflect.ValueOf(g)} 218 ) 219 220 // CopyValue copies a reflect.Value. 221 func CopyValue() { 222 var f func() int 223 var g uintptr 224 v := reflect.ValueOf(f) 225 w := reflect.ValueOf(g) 226 v = w 227 _ = v 228 } 229 230 // CopyValueGlobal copies a reflect.Value that is not a local variable. 231 func CopyValueGlobal() { 232 globalValue1 = globalValue2 233 } 234 235 // CopyValueConcurrently does concurrent copies to a reflect.Value. 236 func CopyValueConcurrently() { 237 var f func() int 238 var g uintptr 239 var v reflect.Value 240 go func() { 241 v = reflect.ValueOf(f) 242 }() 243 go func() { 244 v = reflect.ValueOf(g) 245 }() 246 _ = v 247 } 248 249 // CopyValueViaPointer copies a reflect.Value via a pointer. 250 func CopyValueViaPointer() { 251 var f func() int 252 var g uintptr 253 v := reflect.ValueOf(f) 254 w := reflect.ValueOf(g) 255 p := &v 256 *p = w 257 _ = v 258 } 259 260 type rv = reflect.Value 261 262 // CopyValueEquivalent copies a value with a type equivalent to reflect.Value. 263 func CopyValueEquivalent() { 264 var f func() int 265 var g uintptr 266 v := rv(reflect.ValueOf(f)) 267 w := rv(reflect.ValueOf(g)) 268 v = w 269 _ = v 270 } 271 272 // CopyValueEquivalentViaPointer copies a value with a type equivalent to reflect.Value 273 // via a pointer. 274 func CopyValueEquivalentViaPointer() { 275 var f func() int 276 var g uintptr 277 v := rv(reflect.ValueOf(f)) 278 w := rv(reflect.ValueOf(g)) 279 p := &v 280 *p = w 281 _ = v 282 } 283 284 // rvs is a struct that contains a field of type reflect.Value. 285 type rvs struct { 286 x int 287 v reflect.Value 288 y float32 289 } 290 291 // CopyValueContainingStruct copies a struct containing a reflect.Value. 292 func CopyValueContainingStruct() { 293 var f func() int 294 var g uintptr 295 v := rvs{42, reflect.ValueOf(f), 42} 296 w := rvs{42, reflect.ValueOf(g), 42} 297 v = w 298 _ = v 299 } 300 301 // CopyValueContainingStructViaPointer copies a struct containing a reflect.Value via a pointer. 302 func CopyValueContainingStructViaPointer() { 303 var f func() int 304 var g uintptr 305 v := rvs{42, reflect.ValueOf(f), 42} 306 w := rvs{42, reflect.ValueOf(g), 42} 307 p := &v 308 *p = w 309 _ = v 310 } 311 312 // CopyValueInArray copies a reflect.Value in an array. 313 func CopyValueInArray() { 314 var f func() int 315 var g uintptr 316 v := [1]reflect.Value{reflect.ValueOf(f)} 317 w := [1]reflect.Value{reflect.ValueOf(g)} 318 v = w 319 _ = v 320 } 321 322 // CopyValueInArrayViaPointer copies a reflect.Value in an array via a pointer. 323 func CopyValueInArrayViaPointer() { 324 var f func() int 325 var g uintptr 326 v := [1]reflect.Value{reflect.ValueOf(f)} 327 w := [1]reflect.Value{reflect.ValueOf(g)} 328 p := &v 329 *p = w 330 _ = v 331 } 332 333 // CopyValueInMultipleAssignment copies a reflect.Value using an assignment of 334 // multiple values. 335 func CopyValueInMultipleAssignment() { 336 var f func() int 337 var g uintptr 338 v := reflect.ValueOf(f) 339 w := reflect.ValueOf(g) 340 var a, b, c, d int 341 a, v, b = c, w, d 342 _, _, _, _, _ = v, a, b, c, d 343 } 344 345 // CopyValueInMultipleAssignmentViaPointer copies a reflect.Value via a pointer 346 // using an assignment of multiple values. 347 func CopyValueInMultipleAssignmentViaPointer() { 348 var f func() int 349 var g uintptr 350 v := reflect.ValueOf(f) 351 w := reflect.ValueOf(g) 352 var a, b, c, d int 353 p := &v 354 a, *p, b = c, w, d 355 _, _, _, _, _ = v, a, b, c, d 356 } 357 358 // CopyValueInCommaOk copies a reflect.Value using a "comma-ok" assignment. 359 func CopyValueInCommaOk() { 360 var f func() int 361 var g uintptr 362 v := reflect.ValueOf(f) 363 w := map[int]reflect.Value{1: reflect.ValueOf(g)} 364 var ok bool 365 v, ok = w[1] 366 _, _ = v, ok 367 } 368 369 // CopyValueInStructField copies a reflect.Value field in a struct. 370 func CopyValueInStructField() { 371 var f func() int 372 var g uintptr 373 v := rvs{42, reflect.ValueOf(f), 42} 374 w := rvs{42, reflect.ValueOf(g), 42} 375 v.v = w.v 376 _ = v 377 } 378 379 // CopyValueInStructFieldViaPointer copies a reflect.Value field in a struct 380 // via a pointer. 381 func CopyValueInStructFieldViaPointer() { 382 var f func() int 383 var g uintptr 384 v := &rvs{42, reflect.ValueOf(f), 42} 385 w := rvs{42, reflect.ValueOf(g), 42} 386 v.v = w.v 387 _ = v 388 } 389 390 // RangeValue copies to a reflect.Value using a range clause. 391 func RangeValue() { 392 var x reflect.Value 393 for _, x = range valueSlice1 { 394 } 395 for _, x = range valueSlice2 { 396 } 397 _ = x 398 } 399 400 // RangeValueTwo does concurrent copies to a reflect.Value using range clauses. 401 func RangeValueTwo() { 402 var x reflect.Value 403 go func() { 404 for _, x = range valueSlice1 { 405 } 406 }() 407 go func() { 408 for _, x = range valueSlice2 { 409 } 410 }() 411 _ = x 412 }