github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/prog/encodingexec_test.go (about) 1 // Copyright 2016 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package prog 5 6 import ( 7 "bytes" 8 "encoding/binary" 9 "fmt" 10 "reflect" 11 "testing" 12 13 "github.com/bsm/histogram/v3" 14 ) 15 16 func TestSerializeForExecRandom(t *testing.T) { 17 target, rs, iters := initTest(t) 18 ct := target.DefaultChoiceTable() 19 execSizes := histogram.New(1000) 20 textSizes := histogram.New(1000) 21 totalSize := 0 22 sizes := make(map[string]int) 23 for i := 0; i < iters; i++ { 24 p := target.Generate(rs, 10, ct) 25 buf, err := p.SerializeForExec() 26 if err != nil { 27 t.Fatalf("failed to serialize: %v", err) 28 } 29 got, err := target.DeserializeExec(buf, sizes) 30 if err != nil { 31 t.Fatal(err) 32 } 33 if n, err := ExecCallCount(buf); err != nil { 34 t.Fatal(err) 35 } else if n != len(got.Calls) { 36 t.Fatalf("mismatching number of calls: %v/%v", n, len(got.Calls)) 37 } 38 totalSize += len(buf) 39 execSizes.Add(float64(len(buf))) 40 textSizes.Add(float64(len(p.Serialize()))) 41 } 42 t.Logf("exec sizes: 10%%:%v 50%%:%v 90%%:%v", 43 int(execSizes.Quantile(0.1)), int(execSizes.Quantile(0.5)), int(execSizes.Quantile(0.9))) 44 t.Logf("text sizes: 10%%:%v 50%%:%v 90%%:%v", 45 int(textSizes.Quantile(0.1)), int(textSizes.Quantile(0.5)), int(textSizes.Quantile(0.9))) 46 for what, size := range sizes { 47 t.Logf("%-24v: %5.2f%%", what, float64(size)/float64(totalSize)*100) 48 } 49 } 50 51 // nolint: funlen 52 func TestSerializeForExec(t *testing.T) { 53 target := initTargetTest(t, "test", "64") 54 var ( 55 dataOffset = target.DataOffset 56 ptrSize = target.PtrSize 57 ) 58 callID := func(name string) uint64 { 59 c := target.SyscallMap[name] 60 if c == nil { 61 t.Fatalf("unknown syscall %v", name) 62 } 63 return uint64(c.ID) 64 } 65 tests := []struct { 66 prog string 67 serialized []any 68 decoded *ExecProg 69 }{ 70 { 71 "test()", 72 []any{ 73 callID("test"), ExecNoCopyout, 0, 74 execInstrEOF, 75 }, 76 &ExecProg{ 77 Calls: []ExecCall{ 78 { 79 Meta: target.SyscallMap["test"], 80 Index: ExecNoCopyout, 81 }, 82 }, 83 }, 84 }, 85 { 86 "test$int(0x1, 0x2, 0x3, 0x4, 0x5)", 87 []any{ 88 callID("test$int"), ExecNoCopyout, 5, 89 execArgConst, 8, 1, 90 execArgConst, 1, 2, 91 execArgConst, 2, 3, 92 execArgConst, 4, 4, 93 execArgConst, 8, 5, 94 execInstrEOF, 95 }, 96 nil, 97 }, 98 { 99 "test$align0(&(0x7f0000000000)={0x1, 0x2, 0x3, 0x4, 0x5})", 100 []any{ 101 execInstrCopyin, 0, execArgConst, 2, 1, 102 execInstrCopyin, 4, execArgConst, 4, 2, 103 execInstrCopyin, 8, execArgConst, 1, 3, 104 execInstrCopyin, 10, execArgConst, 2, 4, 105 execInstrCopyin, 16, execArgConst, 8, 5, 106 callID("test$align0"), ExecNoCopyout, 1, execArgAddr64, 0, 107 execInstrEOF, 108 }, 109 nil, 110 }, 111 { 112 "test$align1(&(0x7f0000000000)={0x1, 0x2, 0x3, 0x4, 0x5})", 113 []any{ 114 execInstrCopyin, 0, execArgConst, 2, 1, 115 execInstrCopyin, 2, execArgConst, 4, 2, 116 execInstrCopyin, 6, execArgConst, 1, 3, 117 execInstrCopyin, 7, execArgConst, 2, 4, 118 execInstrCopyin, 9, execArgConst, 8, 5, 119 callID("test$align1"), ExecNoCopyout, 1, execArgAddr64, 0, 120 execInstrEOF, 121 }, 122 nil, 123 }, 124 { 125 "test$align2(&(0x7f0000000000)={0x42, {[0x43]}, {[0x44]}})", 126 []any{ 127 execInstrCopyin, 0, execArgConst, 1, 0x42, 128 execInstrCopyin, 1, execArgConst, 2, 0x43, 129 execInstrCopyin, 4, execArgConst, 2, 0x44, 130 callID("test$align2"), ExecNoCopyout, 1, execArgAddr64, 0, 131 execInstrEOF, 132 }, 133 nil, 134 }, 135 { 136 "test$align3(&(0x7f0000000000)={0x42, {0x43}, {0x44}})", 137 []any{ 138 execInstrCopyin, 0, execArgConst, 1, 0x42, 139 execInstrCopyin, 1, execArgConst, 1, 0x43, 140 execInstrCopyin, 4, execArgConst, 1, 0x44, 141 callID("test$align3"), ExecNoCopyout, 1, execArgAddr64, 0, 142 execInstrEOF, 143 }, 144 nil, 145 }, 146 { 147 "test$align4(&(0x7f0000000000)={{0x42, 0x43}, 0x44})", 148 []any{ 149 execInstrCopyin, 0, execArgConst, 1, 0x42, 150 execInstrCopyin, 1, execArgConst, 2, 0x43, 151 execInstrCopyin, 4, execArgConst, 1, 0x44, 152 callID("test$align4"), ExecNoCopyout, 1, execArgAddr64, 0, 153 execInstrEOF, 154 }, 155 nil, 156 }, 157 { 158 "test$align5(&(0x7f0000000000)={{0x42, []}, {0x43, [0x44, 0x45, 0x46]}, 0x47})", 159 []any{ 160 execInstrCopyin, 0, execArgConst, 8, 0x42, 161 execInstrCopyin, 8, execArgConst, 8, 0x43, 162 execInstrCopyin, 16, execArgConst, 2, 0x44, 163 execInstrCopyin, 18, execArgConst, 2, 0x45, 164 execInstrCopyin, 20, execArgConst, 2, 0x46, 165 execInstrCopyin, 22, execArgConst, 1, 0x47, 166 callID("test$align5"), ExecNoCopyout, 1, execArgAddr64, 0, 167 execInstrEOF, 168 }, 169 nil, 170 }, 171 { 172 "test$align6(&(0x7f0000000000)={0x42, [0x43]})", 173 []any{ 174 execInstrCopyin, 0, execArgConst, 1, 0x42, 175 execInstrCopyin, 4, execArgConst, 4, 0x43, 176 callID("test$align6"), ExecNoCopyout, 1, execArgAddr64, 0, 177 execInstrEOF, 178 }, 179 nil, 180 }, 181 { 182 "test$union0(&(0x7f0000000000)={0x1, @f2=0x2})", 183 []any{ 184 execInstrCopyin, 0, execArgConst, 8, 1, 185 execInstrCopyin, 8, execArgConst, 1, 2, 186 callID("test$union0"), ExecNoCopyout, 1, execArgAddr64, 0, 187 execInstrEOF, 188 }, 189 nil, 190 }, 191 { 192 "test$union1(&(0x7f0000000000)={@f1=0x42, 0x43})", 193 []any{ 194 execInstrCopyin, 0, execArgConst, 4, 0x42, 195 execInstrCopyin, 8, execArgConst, 1, 0x43, 196 callID("test$union1"), ExecNoCopyout, 1, execArgAddr64, 0, 197 execInstrEOF, 198 }, 199 nil, 200 }, 201 { 202 "test$union2(&(0x7f0000000000)={@f1=0x42, 0x43})", 203 []any{ 204 execInstrCopyin, 0, execArgConst, 4, 0x42, 205 execInstrCopyin, 4, execArgConst, 1, 0x43, 206 callID("test$union2"), ExecNoCopyout, 1, execArgAddr64, 0, 207 execInstrEOF, 208 }, 209 nil, 210 }, 211 { 212 "test$array0(&(0x7f0000000000)={0x1, [@f0=0x2, @f1=0x3], 0x4})", 213 []any{ 214 execInstrCopyin, 0, execArgConst, 1, 1, 215 execInstrCopyin, 1, execArgConst, 2, 2, 216 execInstrCopyin, 3, execArgConst, 8, 3, 217 execInstrCopyin, 11, execArgConst, 8, 4, 218 callID("test$array0"), ExecNoCopyout, 1, execArgAddr64, 0, 219 execInstrEOF, 220 }, 221 nil, 222 }, 223 { 224 "test$array1(&(0x7f0000000000)={0x42, \"0102030405\"})", 225 []any{ 226 execInstrCopyin, 0, execArgConst, 1, 0x42, 227 execInstrCopyin, 1, execArgData, 5, []byte{0x01, 0x02, 0x03, 0x04, 0x05}, 228 callID("test$array1"), ExecNoCopyout, 1, execArgAddr64, 0, 229 execInstrEOF, 230 }, 231 nil, 232 }, 233 { 234 "test$array2(&(0x7f0000000000)={0x42, \"aaaaaaaabbbbbbbbccccccccdddddddd\", 0x43})", 235 []any{ 236 execInstrCopyin, 0, execArgConst, 2, 0x42, 237 execInstrCopyin, 2, execArgData, 16, []byte{ 238 0xaa, 0xaa, 0xaa, 0xaa, 239 0xbb, 0xbb, 0xbb, 0xbb, 240 0xcc, 0xcc, 0xcc, 0xcc, 241 0xdd, 0xdd, 0xdd, 0xdd, 242 }, 243 execInstrCopyin, 18, execArgConst, 2, 0x43, 244 callID("test$array2"), ExecNoCopyout, 1, execArgAddr64, 0, 245 execInstrEOF, 246 }, 247 nil, 248 }, 249 { 250 "test$end0(&(0x7f0000000000)={0x42, 0x42, 0x42, 0x42})", 251 []any{ 252 execInstrCopyin, 0, execArgConst, 1, 0x42, 253 execInstrCopyin, 1, execArgConst, 2 | 1<<8, 0x42, 254 execInstrCopyin, 3, execArgConst, 4 | 1<<8, 0x42, 255 execInstrCopyin, 7, execArgConst, 8 | 1<<8, 0x42, 256 callID("test$end0"), ExecNoCopyout, 1, execArgAddr64, 0, 257 execInstrEOF, 258 }, 259 nil, 260 }, 261 { 262 "test$end1(&(0x7f0000000000)={0xe, 0x42, 0x1})", 263 []any{ 264 execInstrCopyin, 0, execArgConst, 2 | 1<<8, 0xe, 265 execInstrCopyin, 2, execArgConst, 4 | 1<<8, 0x42, 266 execInstrCopyin, 6, execArgConst, 8 | 1<<8, 0x1, 267 callID("test$end1"), ExecNoCopyout, 1, execArgAddr64, 0, 268 execInstrEOF, 269 }, 270 nil, 271 }, 272 { 273 "test$bf0(&(0x7f0000000000)={0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42})", 274 []any{ 275 execInstrCopyin, 0, execArgConst, 2 | 0<<16 | 10<<24, 0x42, 276 execInstrCopyin, 8, execArgConst, 8, 0x42, 277 execInstrCopyin, 16, execArgConst, 2 | 0<<16 | 5<<24, 0x42, 278 execInstrCopyin, 16, execArgConst, 2 | 5<<16 | 6<<24, 0x42, 279 execInstrCopyin, 16, execArgConst, 4 | 11<<16 | 15<<24, 0x42, 280 execInstrCopyin, 20, execArgConst, 2 | 0<<16 | 11<<24, 0x42, 281 execInstrCopyin, 22, execArgConst, 2 | 1<<8 | 0<<16 | 11<<24, 0x42, 282 execInstrCopyin, 24, execArgConst, 1, 0x42, 283 callID("test$bf0"), ExecNoCopyout, 1, execArgAddr64, 0, 284 execInstrEOF, 285 }, 286 &ExecProg{ 287 Calls: []ExecCall{ 288 { 289 Meta: target.SyscallMap["test$bf0"], 290 Index: ExecNoCopyout, 291 Args: []ExecArg{ 292 ExecArgConst{ 293 Size: ptrSize, 294 Value: dataOffset, 295 }, 296 }, 297 Copyin: []ExecCopyin{ 298 { 299 Addr: dataOffset + 0, 300 Arg: ExecArgConst{ 301 Size: 2, 302 Value: 0x42, 303 BitfieldOffset: 0, 304 BitfieldLength: 10, 305 }, 306 }, 307 { 308 Addr: dataOffset + 8, 309 Arg: ExecArgConst{ 310 Size: 8, 311 Value: 0x42, 312 }, 313 }, 314 { 315 Addr: dataOffset + 16, 316 Arg: ExecArgConst{ 317 Size: 2, 318 Value: 0x42, 319 BitfieldOffset: 0, 320 BitfieldLength: 5, 321 }, 322 }, 323 { 324 Addr: dataOffset + 16, 325 Arg: ExecArgConst{ 326 Size: 2, 327 Value: 0x42, 328 BitfieldOffset: 5, 329 BitfieldLength: 6, 330 }, 331 }, 332 { 333 Addr: dataOffset + 16, 334 Arg: ExecArgConst{ 335 Size: 4, 336 Value: 0x42, 337 BitfieldOffset: 11, 338 BitfieldLength: 15, 339 }, 340 }, 341 { 342 Addr: dataOffset + 20, 343 Arg: ExecArgConst{ 344 Size: 2, 345 Value: 0x42, 346 BitfieldOffset: 0, 347 BitfieldLength: 11, 348 }, 349 }, 350 { 351 Addr: dataOffset + 22, 352 Arg: ExecArgConst{ 353 Size: 2, 354 Format: FormatBigEndian, 355 Value: 0x42, 356 BitfieldOffset: 0, 357 BitfieldLength: 11, 358 }, 359 }, 360 { 361 Addr: dataOffset + 24, 362 Arg: ExecArgConst{ 363 Size: 1, 364 Value: 0x42, 365 }, 366 }, 367 }, 368 }, 369 }, 370 }, 371 }, 372 { 373 "test$bf1(&(0x7f0000000000)={{0x42, 0x42, 0x42}, 0x42})", 374 []any{ 375 execInstrCopyin, 0, execArgConst, 4 | 0<<16 | 10<<24, 0x42, 376 execInstrCopyin, 0, execArgConst, 4 | 10<<16 | 10<<24, 0x42, 377 execInstrCopyin, 0, execArgConst, 4 | 20<<16 | 10<<24, 0x42, 378 execInstrCopyin, 4, execArgConst, 1, 0x42, 379 callID("test$bf1"), ExecNoCopyout, 1, execArgAddr64, 0, 380 execInstrEOF, 381 }, 382 nil, 383 }, 384 { 385 "test$res1(0xffff)", 386 []any{ 387 callID("test$res1"), ExecNoCopyout, 1, execArgConst, 4, 0xffff, 388 execInstrEOF, 389 }, 390 nil, 391 }, 392 { 393 "test$opt3(0x0)", 394 []any{ 395 callID("test$opt3"), ExecNoCopyout, 1, execArgConst, 8 | 4<<32, 0x64, 396 execInstrEOF, 397 }, 398 nil, 399 }, 400 { 401 // Special value that translates to 0 for all procs. 402 "test$opt3(0xffffffffffffffff)", 403 []any{ 404 callID("test$opt3"), ExecNoCopyout, 1, execArgConst, 8, 0, 405 execInstrEOF, 406 }, 407 nil, 408 }, 409 { 410 // NULL pointer must be encoded os 0. 411 "test$opt1(0x0)", 412 []any{ 413 callID("test$opt1"), ExecNoCopyout, 1, execArgAddr64, -dataOffset, 414 execInstrEOF, 415 }, 416 nil, 417 }, 418 { 419 "test$align7(&(0x7f0000000000)={{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}, 0x42})", 420 []any{ 421 execInstrCopyin, 0, execArgConst, 1 | 0<<16 | 1<<24, 0x1, 422 execInstrCopyin, 0, execArgConst, 1 | 1<<16 | 1<<24, 0x2, 423 execInstrCopyin, 0, execArgConst, 1 | 2<<16 | 1<<24, 0x3, 424 execInstrCopyin, 0, execArgConst, 2 | 3<<16 | 1<<24, 0x4, 425 execInstrCopyin, 0, execArgConst, 2 | 4<<16 | 1<<24, 0x5, 426 execInstrCopyin, 0, execArgConst, 2 | 5<<16 | 1<<24, 0x6, 427 execInstrCopyin, 8, execArgConst, 1, 0x42, 428 callID("test$align7"), ExecNoCopyout, 1, execArgAddr64, 0, 429 execInstrEOF, 430 }, 431 nil, 432 }, 433 { 434 "test$excessive_fields1(0x0)", 435 []any{ 436 callID("test$excessive_fields1"), ExecNoCopyout, 1, execArgAddr64, -dataOffset, 437 execInstrEOF, 438 }, 439 nil, 440 }, 441 { 442 "test$excessive_fields1(0xffffffffffffffff)", 443 []any{ 444 callID("test$excessive_fields1"), ExecNoCopyout, 1, execArgAddr64, 0xffffffffffffffff - dataOffset, 445 execInstrEOF, 446 }, 447 nil, 448 }, 449 { 450 "test$excessive_fields1(0xfffffffffffffffe)", 451 []any{ 452 callID("test$excessive_fields1"), ExecNoCopyout, 1, execArgAddr64, 0x9999999999999999 - dataOffset, 453 execInstrEOF, 454 }, 455 nil, 456 }, 457 { 458 "test$csum_ipv4_tcp(&(0x7f0000000000)={{0x0, 0x1, 0x2}, {{0x0}, \"ab\"}})", 459 []any{ 460 execInstrCopyin, 0, execArgConst, 2, 0x0, 461 execInstrCopyin, 2, execArgConst, 4 | 1<<8, 0x1, 462 execInstrCopyin, 6, execArgConst, 4 | 1<<8, 0x2, 463 execInstrCopyin, 10, execArgConst, 2, 0x0, 464 execInstrCopyin, 12, execArgData, 1, []byte{0xab}, 465 execInstrCopyin, 10, execArgCsum, 2, ExecArgCsumInet, 5, 466 ExecArgCsumChunkData, 2, 4, 467 ExecArgCsumChunkData, 6, 4, 468 ExecArgCsumChunkConst, 0x0600, 2, 469 ExecArgCsumChunkConst, 0x0300, 2, 470 ExecArgCsumChunkData, 10, 3, 471 execInstrCopyin, 0, execArgCsum, 2, ExecArgCsumInet, 1, 472 ExecArgCsumChunkData, 0, 10, 473 callID("test$csum_ipv4_tcp"), ExecNoCopyout, 1, execArgAddr64, 0, 474 execInstrEOF, 475 }, 476 &ExecProg{ 477 Calls: []ExecCall{ 478 { 479 Meta: target.SyscallMap["test$csum_ipv4_tcp"], 480 Index: ExecNoCopyout, 481 Args: []ExecArg{ 482 ExecArgConst{ 483 Value: dataOffset, 484 Size: 8, 485 }, 486 }, 487 Copyin: []ExecCopyin{ 488 { 489 Addr: dataOffset, 490 Arg: ExecArgConst{ 491 Value: 0, 492 Size: 2, 493 }, 494 }, 495 { 496 Addr: dataOffset + 2, 497 Arg: ExecArgConst{ 498 Value: 1, 499 Size: 4, 500 Format: FormatBigEndian, 501 }, 502 }, 503 { 504 Addr: dataOffset + 6, 505 Arg: ExecArgConst{ 506 Value: 2, 507 Size: 4, 508 Format: FormatBigEndian, 509 }, 510 }, 511 { 512 Addr: dataOffset + 10, 513 Arg: ExecArgConst{ 514 Value: 0, 515 Size: 2, 516 }, 517 }, 518 { 519 Addr: dataOffset + 12, 520 Arg: ExecArgData{ 521 Data: []byte{0xab}, 522 }, 523 }, 524 { 525 Addr: dataOffset + 10, 526 Arg: ExecArgCsum{ 527 Size: 2, 528 Kind: ExecArgCsumInet, 529 Chunks: []ExecCsumChunk{ 530 { 531 Kind: ExecArgCsumChunkData, 532 Value: dataOffset + 2, 533 Size: 4, 534 }, 535 { 536 Kind: ExecArgCsumChunkData, 537 Value: dataOffset + 6, 538 Size: 4, 539 }, 540 { 541 Kind: ExecArgCsumChunkConst, 542 Value: 0x0600, 543 Size: 2, 544 }, 545 { 546 Kind: ExecArgCsumChunkConst, 547 Value: 0x0300, 548 Size: 2, 549 }, 550 { 551 Kind: ExecArgCsumChunkData, 552 Value: dataOffset + 10, 553 Size: 3, 554 }, 555 }, 556 }, 557 }, 558 { 559 Addr: dataOffset, 560 Arg: ExecArgCsum{ 561 Size: 2, 562 Kind: ExecArgCsumInet, 563 Chunks: []ExecCsumChunk{ 564 { 565 Kind: ExecArgCsumChunkData, 566 Value: dataOffset, 567 Size: 10, 568 }, 569 }, 570 }, 571 }, 572 }, 573 }, 574 }, 575 }, 576 }, 577 { 578 `test() (fail_nth: 3) 579 test() (fail_nth: 4) 580 test() (async, rerun: 10) 581 `, 582 []any{ 583 execInstrSetProps, 3, 0, 0, 584 callID("test"), ExecNoCopyout, 0, 585 execInstrSetProps, 4, 0, 0, 586 callID("test"), ExecNoCopyout, 0, 587 execInstrSetProps, 0, 1, 10, 588 callID("test"), ExecNoCopyout, 0, 589 execInstrEOF, 590 }, 591 &ExecProg{ 592 Calls: []ExecCall{ 593 { 594 Meta: target.SyscallMap["test"], 595 Index: ExecNoCopyout, 596 Props: CallProps{3, false, 0}, 597 }, 598 { 599 Meta: target.SyscallMap["test"], 600 Index: ExecNoCopyout, 601 Props: CallProps{4, false, 0}, 602 }, 603 { 604 Meta: target.SyscallMap["test"], 605 Index: ExecNoCopyout, 606 Props: CallProps{0, true, 10}, 607 }, 608 }, 609 }, 610 }, 611 { 612 `test$res3(&(0x7f0000000010)=<r0=>0x0) 613 test$res1(r0) 614 `, 615 []any{ 616 callID("test$res3"), ExecNoCopyout, 1, execArgAddr64, 0x10, 617 execInstrCopyout, 0, 0x10, 4, 618 callID("test$res1"), ExecNoCopyout, 1, execArgResult, 4, 0, 0, 0, 0xffff, 619 execInstrEOF, 620 }, 621 &ExecProg{ 622 Calls: []ExecCall{ 623 { 624 Meta: target.SyscallMap["test$res3"], 625 Index: ExecNoCopyout, 626 Args: []ExecArg{ 627 ExecArgConst{ 628 Value: dataOffset + 0x10, 629 Size: 8, 630 }, 631 }, 632 Copyout: []ExecCopyout{ 633 { 634 Index: 0, 635 Addr: dataOffset + 0x10, 636 Size: 4, 637 }, 638 }, 639 }, 640 { 641 Meta: target.SyscallMap["test$res1"], 642 Index: ExecNoCopyout, 643 Args: []ExecArg{ 644 ExecArgResult{ 645 Size: 4, 646 Index: 0, 647 Default: 0xffff, 648 }, 649 }, 650 }, 651 }, 652 Vars: []uint64{0xffff}, 653 }, 654 }, 655 } 656 657 for i, test := range tests { 658 i, test := i, test 659 t.Run(fmt.Sprintf("%v:%v", i, test.prog), func(t *testing.T) { 660 p, err := target.Deserialize([]byte(test.prog), Strict) 661 if err != nil { 662 t.Fatalf("failed to deserialize prog %v: %v", i, err) 663 } 664 data, err := p.SerializeForExec() 665 if err != nil { 666 t.Fatalf("failed to serialize: %v", err) 667 } 668 want := binary.AppendVarint(nil, int64(len(p.Calls))) 669 for _, e := range test.serialized { 670 switch elem := e.(type) { 671 case uint64: 672 want = binary.AppendVarint(want, int64(elem)) 673 case int: 674 want = binary.AppendVarint(want, int64(elem)) 675 case []byte: 676 want = append(want, elem...) 677 default: 678 t.Fatalf("unexpected elem type %T %#v", e, e) 679 } 680 } 681 if !bytes.Equal(data, want) { 682 t.Logf("want: %v", test.serialized) 683 t.Logf("got: %q", data) 684 t.Fatalf("mismatch") 685 } 686 decoded, err := target.DeserializeExec(data, nil) 687 if err != nil { 688 t.Fatal(err) 689 } 690 if test.decoded != nil && !reflect.DeepEqual(decoded, *test.decoded) { 691 t.Logf("want: %#v", *test.decoded) 692 t.Logf("got: %#v", decoded) 693 t.Fatalf("decoded mismatch") 694 } 695 }) 696 } 697 } 698 699 func TestSerializeForExecOverflow(t *testing.T) { 700 target := initTargetTest(t, "test", "64") 701 type Test struct { 702 name string 703 overflow bool 704 gen func(w *bytes.Buffer) 705 } 706 tests := []Test{ 707 { 708 name: "few-resources", 709 overflow: false, 710 gen: func(w *bytes.Buffer) { 711 for i := 0; i < execMaxCommands-10; i++ { 712 fmt.Fprintf(w, "r%v = test$res0()\ntest$res1(r%v)\n", i, i) 713 } 714 }, 715 }, 716 { 717 name: "overflow-resources", 718 overflow: true, 719 gen: func(w *bytes.Buffer) { 720 for i := 0; i < execMaxCommands+1; i++ { 721 fmt.Fprintf(w, "r%v = test$res0()\ntest$res1(r%v)\n", i, i) 722 } 723 }, 724 }, 725 { 726 name: "no-verflow-buffer", 727 overflow: false, 728 gen: func(w *bytes.Buffer) { 729 fmt.Fprintf(w, "r0 = test$res0()\n") 730 for i := 0; i < 58e3; i++ { 731 fmt.Fprintf(w, "test$res1(r0)\n") 732 } 733 }, 734 }, 735 { 736 name: "overflow-buffer", 737 overflow: true, 738 gen: func(w *bytes.Buffer) { 739 fmt.Fprintf(w, "r0 = test$res0()\n") 740 for i := 0; i < 4e5; i++ { 741 fmt.Fprintf(w, "test$res1(r0)\n") 742 } 743 }, 744 }, 745 } 746 for _, test := range tests { 747 t.Run(test.name, func(t *testing.T) { 748 data := new(bytes.Buffer) 749 test.gen(data) 750 p, err := target.Deserialize(data.Bytes(), Strict) 751 if err != nil { 752 t.Fatal(err) 753 } 754 _, err = p.SerializeForExec() 755 if test.overflow && err == nil { 756 t.Fatalf("want overflow but got no error") 757 } 758 if !test.overflow && err != nil { 759 t.Fatalf("want no overflow but got %v", err) 760 } 761 }) 762 } 763 }