github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/prog/encoding.go (about) 1 // Copyright 2015 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/hex" 9 "fmt" 10 "reflect" 11 "strconv" 12 "strings" 13 14 "github.com/google/syzkaller/pkg/image" 15 ) 16 17 // String generates a very compact program description (mostly for debug output). 18 func (p *Prog) String() string { 19 buf := new(bytes.Buffer) 20 for i, c := range p.Calls { 21 if i != 0 { 22 fmt.Fprintf(buf, "-") 23 } 24 fmt.Fprintf(buf, "%v", c.Meta.Name) 25 } 26 return buf.String() 27 } 28 29 type SerializeFlag int 30 31 const ( 32 // Include all field values, even if they have default values. 33 Verbose SerializeFlag = 0 34 // Don't serialize compressed fs images. 35 // This is used in coverage report generation to prevent the bloating of the resulting HTML file. 36 SkipImages SerializeFlag = 1 37 ) 38 39 func (p *Prog) Serialize(flags ...SerializeFlag) []byte { 40 p.debugValidate() 41 ctx := &serializer{ 42 target: p.Target, 43 buf: new(bytes.Buffer), 44 vars: make(map[*ResultArg]int), 45 } 46 for _, flag := range flags { 47 switch flag { 48 case Verbose: 49 ctx.verbose = true 50 case SkipImages: 51 ctx.skipImages = true 52 } 53 } 54 for _, c := range p.Calls { 55 ctx.call(c) 56 } 57 return ctx.buf.Bytes() 58 } 59 60 func (p *Prog) SerializeVerbose() []byte { 61 return p.Serialize(Verbose) 62 } 63 64 type serializer struct { 65 target *Target 66 buf *bytes.Buffer 67 vars map[*ResultArg]int 68 varSeq int 69 verbose bool 70 skipImages bool 71 } 72 73 func (ctx *serializer) print(text string) { 74 ctx.printf("%v", text) 75 } 76 77 func (ctx *serializer) printf(text string, args ...interface{}) { 78 fmt.Fprintf(ctx.buf, text, args...) 79 } 80 81 func (ctx *serializer) allocVarID(arg *ResultArg) int { 82 id := ctx.varSeq 83 ctx.varSeq++ 84 ctx.vars[arg] = id 85 return id 86 } 87 88 func (ctx *serializer) call(c *Call) { 89 if c.Ret != nil && len(c.Ret.uses) != 0 { 90 ctx.printf("r%v = ", ctx.allocVarID(c.Ret)) 91 } 92 ctx.printf("%v(", c.Meta.Name) 93 for i, a := range c.Args { 94 if IsPad(a.Type()) { 95 continue 96 } 97 if i != 0 { 98 ctx.printf(", ") 99 } 100 ctx.arg(a) 101 } 102 ctx.print(")") 103 104 anyChangedProps := false 105 c.Props.ForeachProp(func(name, key string, value reflect.Value) { 106 // reflect.Value.IsZero is added in go1.13, not available in Appengine SDK. 107 if reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) { 108 return 109 } 110 111 if !anyChangedProps { 112 ctx.print(" (") 113 anyChangedProps = true 114 } else { 115 ctx.print(", ") 116 } 117 118 ctx.print(key) 119 switch kind := value.Kind(); kind { 120 case reflect.Int: 121 ctx.printf(": %d", value.Int()) 122 case reflect.Bool: 123 default: 124 panic("unable to serialize call prop of type " + kind.String()) 125 } 126 }) 127 if anyChangedProps { 128 ctx.printf(")") 129 } 130 131 ctx.printf("\n") 132 } 133 134 func (ctx *serializer) arg(arg Arg) { 135 if arg == nil { 136 ctx.printf("nil") 137 return 138 } 139 arg.serialize(ctx) 140 } 141 142 func (a *ConstArg) serialize(ctx *serializer) { 143 ctx.printf("0x%x", a.Val) 144 } 145 146 func (a *PointerArg) serialize(ctx *serializer) { 147 if a.IsSpecial() { 148 ctx.printf("0x%x", a.Address) 149 return 150 } 151 target := ctx.target 152 ctx.printf("&%v", target.serializeAddr(a)) 153 if a.Res != nil && !ctx.verbose && isDefault(a.Res) && !target.isAnyPtr(a.Type()) { 154 return 155 } 156 ctx.printf("=") 157 if target.isAnyPtr(a.Type()) { 158 ctx.printf("ANY=") 159 } 160 ctx.arg(a.Res) 161 } 162 163 func (a *DataArg) serialize(ctx *serializer) { 164 typ := a.Type().(*BufferType) 165 if a.Dir() == DirOut { 166 ctx.printf("\"\"/%v", a.Size()) 167 return 168 } 169 data := a.Data() 170 if typ.IsCompressed() { 171 if ctx.skipImages { 172 ctx.printf(`"<<IMAGE>>"`) 173 } else { 174 serializeCompressedData(ctx.buf, data) 175 } 176 } else { 177 // Statically typed data will be padded with 0s during deserialization, 178 // so we can strip them here for readability always. For variable-size 179 // data we strip trailing 0s only if we strip enough of them. 180 sz := len(data) 181 for len(data) >= 2 && data[len(data)-1] == 0 && data[len(data)-2] == 0 { 182 data = data[:len(data)-1] 183 } 184 if typ.Varlen() && len(data)+8 >= sz { 185 data = data[:sz] 186 } 187 serializeData(ctx.buf, data, isReadableDataType(typ)) 188 if typ.Varlen() && sz != len(data) { 189 ctx.printf("/%v", sz) 190 } 191 } 192 } 193 194 func (a *GroupArg) serialize(ctx *serializer) { 195 var delims []byte 196 switch a.Type().(type) { 197 case *StructType: 198 delims = []byte{'{', '}'} 199 case *ArrayType: 200 delims = []byte{'[', ']'} 201 default: 202 panic("unknown group type") 203 } 204 ctx.buf.WriteByte(delims[0]) 205 lastNonDefault := len(a.Inner) - 1 206 if !ctx.verbose && a.fixedInnerSize() { 207 for ; lastNonDefault >= 0; lastNonDefault-- { 208 if !isDefault(a.Inner[lastNonDefault]) { 209 break 210 } 211 } 212 } 213 for i := 0; i <= lastNonDefault; i++ { 214 arg1 := a.Inner[i] 215 if arg1 != nil && IsPad(arg1.Type()) { 216 continue 217 } 218 if i != 0 { 219 ctx.printf(", ") 220 } 221 ctx.arg(arg1) 222 } 223 ctx.buf.WriteByte(delims[1]) 224 } 225 226 func (a *UnionArg) serialize(ctx *serializer) { 227 typ := a.Type().(*UnionType) 228 ctx.printf("@%v", typ.Fields[a.Index].Name) 229 if !ctx.verbose && isDefault(a.Option) { 230 return 231 } 232 ctx.printf("=") 233 ctx.arg(a.Option) 234 } 235 236 func (a *ResultArg) serialize(ctx *serializer) { 237 if len(a.uses) != 0 { 238 ctx.printf("<r%v=>", ctx.allocVarID(a)) 239 } 240 if a.Res == nil { 241 ctx.printf("0x%x", a.Val) 242 return 243 } 244 id, ok := ctx.vars[a.Res] 245 if !ok { 246 panic("no result") 247 } 248 ctx.printf("r%v", id) 249 if a.OpDiv != 0 { 250 ctx.printf("/%v", a.OpDiv) 251 } 252 if a.OpAdd != 0 { 253 ctx.printf("+%v", a.OpAdd) 254 } 255 } 256 257 type DeserializeMode int 258 259 const ( 260 // In strict mode deserialization fails if the program is malformed in any way. 261 // This mode is used for manually written programs to ensure that they are correct. 262 Strict DeserializeMode = iota 263 // In non-strict mode malformed programs silently fixed in a best-effort way, 264 // e.g. missing/wrong arguments are replaced with default values. 265 // This mode is used for the corpus programs to "repair" them after descriptions changes. 266 NonStrict 267 // Unsafe mode is used for VM checking programs. In this mode programs are not fixed 268 // for safety, e.g. can access global files, issue prohibited ioctl's, disabled syscalls, etc. 269 StrictUnsafe 270 NonStrictUnsafe 271 ) 272 273 func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, error) { 274 defer func() { 275 if err := recover(); err != nil { 276 panic(fmt.Errorf("%v\ntarget: %v/%v, rev: %v, mode=%v, prog:\n%q", 277 err, target.OS, target.Arch, GitRevision, mode, data)) 278 } 279 }() 280 strict := mode == Strict || mode == StrictUnsafe 281 unsafe := mode == StrictUnsafe || mode == NonStrictUnsafe 282 p := newParser(target, data, strict, unsafe) 283 prog, err := p.parseProg() 284 if err := p.Err(); err != nil { 285 return nil, err 286 } 287 if err != nil { 288 return nil, err 289 } 290 // This validation is done even in non-debug mode because deserialization 291 // procedure does not catch all bugs (e.g. mismatched types). 292 // And we can receive bad programs from corpus and hub. 293 if err := prog.validateWithOpts(validationOptions{ 294 // Don't validate auto-set conditional fields. We'll patch them later. 295 ignoreTransient: true, 296 }); err != nil { 297 return nil, err 298 } 299 p.fixupConditionals(prog) 300 if p.autos != nil { 301 p.fixupAutos(prog) 302 } 303 if !unsafe { 304 if err := prog.sanitize(!strict); err != nil { 305 return nil, err 306 } 307 } 308 return prog, nil 309 } 310 311 func (p *parser) parseProg() (*Prog, error) { 312 prog := &Prog{ 313 Target: p.target, 314 isUnsafe: p.unsafe, 315 } 316 for p.Scan() { 317 if p.EOF() { 318 if p.comment != "" { 319 prog.Comments = append(prog.Comments, p.comment) 320 p.comment = "" 321 } 322 continue 323 } 324 if p.Char() == '#' { 325 if p.comment != "" { 326 prog.Comments = append(prog.Comments, p.comment) 327 } 328 p.comment = strings.TrimSpace(p.s[p.i+1:]) 329 continue 330 } 331 name := p.Ident() 332 r := "" 333 if p.Char() == '=' { 334 r = name 335 p.Parse('=') 336 name = p.Ident() 337 } 338 meta := p.target.SyscallMap[name] 339 if meta == nil { 340 return nil, fmt.Errorf("unknown syscall %v", name) 341 } 342 c := MakeCall(meta, nil) 343 c.Comment = p.comment 344 prog.Calls = append(prog.Calls, c) 345 p.Parse('(') 346 for i := 0; p.Char() != ')'; i++ { 347 if i >= len(meta.Args) { 348 p.eatExcessive(false, "excessive syscall arguments") 349 break 350 } 351 field := meta.Args[i] 352 if IsPad(field.Type) { 353 return nil, fmt.Errorf("padding in syscall %v arguments", name) 354 } 355 arg, err := p.parseArg(field.Type, DirIn) 356 if err != nil { 357 return nil, err 358 } 359 c.Args = append(c.Args, arg) 360 if p.Char() != ')' { 361 p.Parse(',') 362 } 363 } 364 p.Parse(')') 365 366 if !p.EOF() && p.Char() == '(' { 367 p.Parse('(') 368 c.Props = p.parseCallProps() 369 p.Parse(')') 370 } 371 372 if !p.EOF() { 373 if p.Char() != '#' { 374 return nil, fmt.Errorf("tailing data (line #%v)", p.l) 375 } 376 if c.Comment != "" { 377 prog.Comments = append(prog.Comments, c.Comment) 378 } 379 c.Comment = strings.TrimSpace(p.s[p.i+1:]) 380 } 381 for i := len(c.Args); i < len(meta.Args); i++ { 382 p.strictFailf("missing syscall args") 383 c.Args = append(c.Args, meta.Args[i].DefaultArg(DirIn)) 384 } 385 if len(c.Args) != len(meta.Args) { 386 return nil, fmt.Errorf("wrong call arg count: %v, want %v", len(c.Args), len(meta.Args)) 387 } 388 if r != "" && c.Ret != nil { 389 p.vars[r] = c.Ret 390 } 391 p.comment = "" 392 } 393 if p.comment != "" { 394 prog.Comments = append(prog.Comments, p.comment) 395 } 396 return prog, nil 397 } 398 399 func (p *parser) parseCallProps() CallProps { 400 nameToValue := map[string]reflect.Value{} 401 callProps := CallProps{} 402 callProps.ForeachProp(func(_, key string, value reflect.Value) { 403 nameToValue[key] = value 404 }) 405 406 for p.e == nil && p.Char() != ')' { 407 propName := p.Ident() 408 value, ok := nameToValue[propName] 409 if !ok { 410 p.eatExcessive(true, "unknown call property: %s", propName) 411 if p.Char() == ',' { 412 p.Parse(',') 413 } 414 continue 415 } 416 switch kind := value.Kind(); kind { 417 case reflect.Int: 418 p.Parse(':') 419 strVal := p.Ident() 420 intV, err := strconv.ParseInt(strVal, 0, 64) 421 if err != nil { 422 p.strictFailf("invalid int value: %s", strVal) 423 } else { 424 value.SetInt(intV) 425 } 426 case reflect.Bool: 427 value.SetBool(true) 428 default: 429 panic("unable to handle call props of type " + kind.String()) 430 } 431 if p.Char() != ')' { 432 p.Parse(',') 433 } 434 } 435 return callProps 436 } 437 438 func (p *parser) parseArg(typ Type, dir Dir) (Arg, error) { 439 r := "" 440 if p.Char() == '<' { 441 p.Parse('<') 442 r = p.Ident() 443 p.Parse('=') 444 p.Parse('>') 445 } 446 arg, err := p.parseArgImpl(typ, dir) 447 if err != nil { 448 return nil, err 449 } 450 if arg == nil { 451 if typ != nil { 452 arg = typ.DefaultArg(dir) 453 } else if r != "" { 454 return nil, fmt.Errorf("named nil argument") 455 } 456 } 457 if r != "" { 458 if res, ok := arg.(*ResultArg); ok { 459 p.vars[r] = res 460 } else { 461 p.strictFailf("variable %v doesn't refers to a resource", r) 462 } 463 } 464 return arg, nil 465 } 466 467 func (p *parser) parseArgImpl(typ Type, dir Dir) (Arg, error) { 468 if typ == nil && p.Char() != 'n' { 469 p.eatExcessive(true, "non-nil argument for nil type") 470 return nil, nil 471 } 472 switch p.Char() { 473 case '0': 474 return p.parseArgInt(typ, dir) 475 case 'r': 476 return p.parseArgRes(typ, dir) 477 case '&': 478 return p.parseArgAddr(typ, dir) 479 case '"', '\'': 480 return p.parseArgString(typ, dir) 481 case '{': 482 return p.parseArgStruct(typ, dir) 483 case '[': 484 return p.parseArgArray(typ, dir) 485 case '@': 486 return p.parseArgUnion(typ, dir) 487 case 'n': 488 p.Parse('n') 489 p.Parse('i') 490 p.Parse('l') 491 return nil, nil 492 case 'A': 493 p.Parse('A') 494 p.Parse('U') 495 p.Parse('T') 496 p.Parse('O') 497 return p.parseAuto(typ, dir) 498 default: 499 return nil, fmt.Errorf("failed to parse argument at '%c' (line #%v/%v: %v)", 500 p.Char(), p.l, p.i, highlightError(p.s, p.i)) 501 } 502 } 503 504 func (p *parser) parseArgInt(typ Type, dir Dir) (Arg, error) { 505 val := p.Ident() 506 v, err := strconv.ParseUint(val, 0, 64) 507 if err != nil { 508 return nil, fmt.Errorf("wrong arg value '%v': %w", val, err) 509 } 510 switch typ.(type) { 511 case *ConstType, *IntType, *FlagsType, *ProcType, *CsumType: 512 arg := Arg(MakeConstArg(typ, dir, v)) 513 if dir == DirOut && !typ.isDefaultArg(arg) { 514 p.strictFailf("out arg %v has non-default value: %v", typ, v) 515 arg = typ.DefaultArg(dir) 516 } 517 return arg, nil 518 case *LenType: 519 return MakeConstArg(typ, dir, v), nil 520 case *ResourceType: 521 return MakeResultArg(typ, dir, nil, v), nil 522 case *PtrType, *VmaType: 523 index := -v % uint64(len(p.target.SpecialPointers)) 524 return MakeSpecialPointerArg(typ, dir, index), nil 525 default: 526 p.eatExcessive(true, "wrong int arg %T", typ) 527 return typ.DefaultArg(dir), nil 528 } 529 } 530 531 func (p *parser) parseAuto(typ Type, dir Dir) (Arg, error) { 532 switch t1 := typ.(type) { 533 case *ConstType, *LenType, *CsumType: 534 return p.auto(MakeConstArg(typ, dir, 0)), nil 535 case *StructType: 536 var inner []Arg 537 for len(inner) < len(t1.Fields) { 538 field := t1.Fields[len(inner)] 539 innerArg, err := p.parseAuto(field.Type, dir) 540 if err != nil { 541 return nil, err 542 } 543 inner = append(inner, innerArg) 544 } 545 return MakeGroupArg(typ, dir, inner), nil 546 default: 547 return nil, fmt.Errorf("wrong type %T for AUTO", typ) 548 } 549 } 550 551 func (p *parser) parseArgRes(typ Type, dir Dir) (Arg, error) { 552 id := p.Ident() 553 var div, add uint64 554 if p.Char() == '/' { 555 p.Parse('/') 556 op := p.Ident() 557 v, err := strconv.ParseUint(op, 0, 64) 558 if err != nil { 559 return nil, fmt.Errorf("wrong result div op: '%v'", op) 560 } 561 div = v 562 } 563 if p.Char() == '+' { 564 p.Parse('+') 565 op := p.Ident() 566 v, err := strconv.ParseUint(op, 0, 64) 567 if err != nil { 568 return nil, fmt.Errorf("wrong result add op: '%v'", op) 569 } 570 add = v 571 } 572 v := p.vars[id] 573 if v == nil { 574 p.strictFailf("undeclared variable %v", id) 575 return typ.DefaultArg(dir), nil 576 } 577 arg := MakeResultArg(typ, dir, v, 0) 578 arg.OpDiv = div 579 arg.OpAdd = add 580 return arg, nil 581 } 582 583 func (p *parser) parseArgAddr(typ Type, dir Dir) (Arg, error) { 584 var elem Type 585 elemDir := DirInOut 586 squashableElem := false 587 switch t1 := typ.(type) { 588 case *PtrType: 589 elem, elemDir, squashableElem = t1.Elem, t1.ElemDir, t1.SquashableElem 590 case *VmaType: 591 default: 592 p.eatExcessive(true, "wrong addr arg %T", typ) 593 return typ.DefaultArg(dir), nil 594 } 595 p.Parse('&') 596 auto := false 597 var addr, vmaSize uint64 598 if p.Char() == 'A' { 599 p.Parse('A') 600 p.Parse('U') 601 p.Parse('T') 602 p.Parse('O') 603 if elem == nil { 604 return nil, fmt.Errorf("vma type can't be AUTO") 605 } 606 auto = true 607 } else { 608 var err error 609 addr, vmaSize, err = p.parseAddr() 610 if err != nil { 611 return nil, err 612 } 613 } 614 var inner Arg 615 if p.Char() == '=' { 616 p.Parse('=') 617 if p.HasNext("ANY") { 618 p.Parse('A') 619 p.Parse('N') 620 p.Parse('Y') 621 p.Parse('=') 622 if squashableElem { 623 anyPtr := p.target.getAnyPtrType(typ.Size()) 624 typ, elem, elemDir = anyPtr, anyPtr.Elem, anyPtr.ElemDir 625 } 626 } 627 var err error 628 inner, err = p.parseArg(elem, elemDir) 629 if err != nil { 630 return nil, err 631 } 632 } 633 if elem == nil { 634 if addr%p.target.PageSize != 0 { 635 p.strictFailf("unaligned vma address 0x%x", addr) 636 addr &= ^(p.target.PageSize - 1) 637 } 638 return MakeVmaPointerArg(typ, dir, addr, vmaSize), nil 639 } 640 if inner == nil { 641 inner = elem.DefaultArg(elemDir) 642 } 643 arg := MakePointerArg(typ, dir, addr, inner) 644 if auto { 645 p.auto(arg) 646 } 647 return arg, nil 648 } 649 650 func (p *parser) parseArgString(t Type, dir Dir) (Arg, error) { 651 typ, ok := t.(*BufferType) 652 if !ok { 653 p.eatExcessive(true, "wrong string arg") 654 return t.DefaultArg(dir), nil 655 } 656 data, b64, err := p.deserializeData() 657 if err != nil { 658 return nil, err 659 } 660 // Check compressed data for validity. 661 if typ.IsCompressed() { 662 if err := image.DecompressCheck(data); err != nil { 663 p.strictFailf("invalid compressed data in arg: %v", err) 664 // In non-strict mode, empty the data slice. 665 data = image.Compress(nil) 666 } 667 } 668 size := ^uint64(0) 669 if p.Char() == '/' && !b64 { 670 p.Parse('/') 671 sizeStr := p.Ident() 672 size, err = strconv.ParseUint(sizeStr, 0, 64) 673 if err != nil { 674 return nil, fmt.Errorf("failed to parse buffer size: %q", sizeStr) 675 } 676 maxMem := p.target.NumPages * p.target.PageSize 677 if size > maxMem { 678 p.strictFailf("too large string argument %v", size) 679 size = maxMem 680 } 681 } 682 if !typ.Varlen() { 683 size = typ.Size() 684 } else if size == ^uint64(0) { 685 size = uint64(len(data)) 686 } 687 if dir == DirOut { 688 return MakeOutDataArg(typ, dir, size), nil 689 } 690 if diff := int(size) - len(data); diff > 0 { 691 data = append(data, make([]byte, diff)...) 692 } 693 data = data[:size] 694 if (typ.Kind == BufferString || typ.Kind == BufferGlob) && 695 len(typ.Values) != 0 && 696 // AUTOGENERATED will be padded by 0's. 697 !strings.HasPrefix(typ.Values[0], "AUTOGENERATED") { 698 matched := false 699 for _, val := range typ.Values { 700 if string(data) == val { 701 matched = true 702 break 703 } 704 } 705 if !matched { 706 p.strictFailf("bad string value %q, expect %q", data, typ.Values) 707 data = []byte(typ.Values[0]) 708 } 709 } 710 return MakeDataArg(typ, dir, data), nil 711 } 712 713 func (p *parser) parseArgStruct(typ Type, dir Dir) (Arg, error) { 714 p.Parse('{') 715 t1, ok := typ.(*StructType) 716 if !ok { 717 p.eatExcessive(false, "wrong struct arg for %q", typ.Name()) 718 p.Parse('}') 719 return typ.DefaultArg(dir), nil 720 } 721 var inner []Arg 722 for i := 0; p.Char() != '}'; i++ { 723 if i >= len(t1.Fields) { 724 p.eatExcessive(false, "excessive struct %v fields", typ.Name()) 725 break 726 } 727 field := t1.Fields[i] 728 if IsPad(field.Type) { 729 inner = append(inner, MakeConstArg(field.Type, field.Dir(dir), 0)) 730 } else { 731 arg, err := p.parseArg(field.Type, field.Dir(dir)) 732 if err != nil { 733 return nil, err 734 } 735 inner = append(inner, arg) 736 if p.Char() != '}' { 737 p.Parse(',') 738 } 739 } 740 } 741 p.Parse('}') 742 for len(inner) < len(t1.Fields) { 743 field := t1.Fields[len(inner)] 744 if !IsPad(field.Type) { 745 p.strictFailf("missing struct %v fields %v/%v", typ.Name(), len(inner), len(t1.Fields)) 746 } 747 inner = append(inner, field.Type.DefaultArg(field.Dir(dir))) 748 } 749 return MakeGroupArg(typ, dir, inner), nil 750 } 751 752 func (p *parser) parseArgArray(typ Type, dir Dir) (Arg, error) { 753 p.Parse('[') 754 t1, ok := typ.(*ArrayType) 755 if !ok { 756 p.eatExcessive(false, "wrong array arg %T", typ) 757 p.Parse(']') 758 return typ.DefaultArg(dir), nil 759 } 760 var inner []Arg 761 for i := 0; p.Char() != ']'; i++ { 762 arg, err := p.parseArg(t1.Elem, dir) 763 if err != nil { 764 return nil, err 765 } 766 inner = append(inner, arg) 767 if p.Char() != ']' { 768 p.Parse(',') 769 } 770 } 771 p.Parse(']') 772 if t1.Kind == ArrayRangeLen && t1.RangeBegin == t1.RangeEnd { 773 for uint64(len(inner)) < t1.RangeBegin { 774 p.strictFailf("missing array elements") 775 inner = append(inner, t1.Elem.DefaultArg(dir)) 776 } 777 inner = inner[:t1.RangeBegin] 778 } 779 return MakeGroupArg(typ, dir, inner), nil 780 } 781 782 func (p *parser) parseArgUnion(typ Type, dir Dir) (Arg, error) { 783 t1, ok := typ.(*UnionType) 784 if !ok { 785 p.eatExcessive(true, "wrong union arg for %q", typ.Name()) 786 return typ.DefaultArg(dir), nil 787 } 788 p.Parse('@') 789 name := p.Ident() 790 var ( 791 optType Type 792 optDir Dir 793 options []string 794 ) 795 index := -1 796 for i, field := range t1.Fields { 797 if name == field.Name { 798 optType, index, optDir = field.Type, i, field.Dir(dir) 799 break 800 } 801 options = append(options, fmt.Sprintf("%q", field.Name)) 802 } 803 if optType == nil { 804 p.eatExcessive(true, "wrong option %q of union %q, available options are: %s", 805 name, typ.Name(), strings.Join(options, ", ")) 806 return typ.DefaultArg(dir), nil 807 } 808 var opt Arg 809 if p.Char() == '=' { 810 p.Parse('=') 811 var err error 812 opt, err = p.parseArg(optType, optDir) 813 if err != nil { 814 return nil, err 815 } 816 } else { 817 opt = optType.DefaultArg(optDir) 818 } 819 return MakeUnionArg(typ, dir, opt, index), nil 820 } 821 822 // Eats excessive call arguments and struct fields to recover after description changes. 823 func (p *parser) eatExcessive(stopAtComma bool, what string, args ...interface{}) { 824 p.strictFailf(what, args...) 825 paren, brack, brace := 0, 0, 0 826 for !p.EOF() && p.e == nil { 827 ch := p.Char() 828 switch ch { 829 case '(': 830 paren++ 831 case ')': 832 if paren == 0 { 833 return 834 } 835 paren-- 836 case '[': 837 brack++ 838 case ']': 839 if brack == 0 { 840 return 841 } 842 brack-- 843 case '{': 844 brace++ 845 case '}': 846 if brace == 0 { 847 return 848 } 849 brace-- 850 case ',': 851 if stopAtComma && paren == 0 && brack == 0 && brace == 0 { 852 return 853 } 854 case '\'', '"': 855 p.Parse(ch) 856 for !p.EOF() && p.Char() != ch { 857 p.Parse(p.Char()) 858 } 859 if p.EOF() { 860 return 861 } 862 } 863 p.Parse(ch) 864 } 865 } 866 867 const ( 868 encodingAddrBase = 0x7f0000000000 869 ) 870 871 func (target *Target) serializeAddr(arg *PointerArg) string { 872 ssize := "" 873 if arg.VmaSize != 0 { 874 ssize = fmt.Sprintf("/0x%x", arg.VmaSize) 875 } 876 return fmt.Sprintf("(0x%x%v)", encodingAddrBase+arg.Address, ssize) 877 } 878 879 func (p *parser) parseAddr() (uint64, uint64, error) { 880 p.Parse('(') 881 pstr := p.Ident() 882 addr, err := strconv.ParseUint(pstr, 0, 64) 883 if err != nil { 884 return 0, 0, fmt.Errorf("failed to parse addr: %q", pstr) 885 } 886 addr -= encodingAddrBase 887 target := p.target 888 var vmaSize uint64 889 if p.Char() == '/' { 890 p.Parse('/') 891 pstr := p.Ident() 892 size, err := strconv.ParseUint(pstr, 0, 64) 893 if err != nil { 894 return 0, 0, fmt.Errorf("failed to parse addr size: %q", pstr) 895 } 896 addr = addr & ^(target.PageSize - 1) 897 vmaSize = (size + target.PageSize - 1) & ^(target.PageSize - 1) 898 if vmaSize == 0 { 899 vmaSize = target.PageSize 900 } 901 if !p.unsafe { 902 maxMem := target.NumPages * target.PageSize 903 vmaSize = min(vmaSize, maxMem) 904 addr = min(addr, maxMem-vmaSize) 905 } 906 } 907 p.Parse(')') 908 return addr, vmaSize, nil 909 } 910 911 func serializeData(buf *bytes.Buffer, data []byte, readable bool) { 912 if !readable && !isReadableData(data) { 913 fmt.Fprintf(buf, "\"%v\"", hex.EncodeToString(data)) 914 return 915 } 916 buf.WriteByte('\'') 917 encodeData(buf, data, true, false) 918 buf.WriteByte('\'') 919 } 920 921 func serializeCompressedData(buf *bytes.Buffer, data []byte) { 922 buf.WriteByte('"') 923 buf.WriteByte('$') 924 buf.Write(image.EncodeB64(data)) 925 buf.WriteByte('"') 926 } 927 928 func EncodeData(buf *bytes.Buffer, data []byte, readable bool) { 929 if !readable && isReadableData(data) { 930 readable = true 931 } 932 encodeData(buf, data, readable, true) 933 } 934 935 func encodeData(buf *bytes.Buffer, data []byte, readable, cstr bool) { 936 for _, v := range data { 937 if !readable { 938 lo, hi := byteToHex(v) 939 buf.Write([]byte{'\\', 'x', hi, lo}) 940 continue 941 } 942 switch v { 943 case '\a': 944 buf.Write([]byte{'\\', 'a'}) 945 case '\b': 946 buf.Write([]byte{'\\', 'b'}) 947 case '\f': 948 buf.Write([]byte{'\\', 'f'}) 949 case '\n': 950 buf.Write([]byte{'\\', 'n'}) 951 case '\r': 952 buf.Write([]byte{'\\', 'r'}) 953 case '\t': 954 buf.Write([]byte{'\\', 't'}) 955 case '\v': 956 buf.Write([]byte{'\\', 'v'}) 957 case '\'': 958 buf.Write([]byte{'\\', '\''}) 959 case '"': 960 buf.Write([]byte{'\\', '"'}) 961 case '\\': 962 buf.Write([]byte{'\\', '\\'}) 963 default: 964 if isPrintable(v) { 965 buf.WriteByte(v) 966 } else { 967 if cstr { 968 // We would like to use hex encoding with \x, 969 // but C's \x is hard to use: it can contain _any_ number of hex digits 970 // (not just 2 or 4), so later non-hex encoded chars will glue to \x. 971 c0 := (v>>6)&0x7 + '0' 972 c1 := (v>>3)&0x7 + '0' 973 c2 := (v>>0)&0x7 + '0' 974 buf.Write([]byte{'\\', c0, c1, c2}) 975 } else { 976 lo, hi := byteToHex(v) 977 buf.Write([]byte{'\\', 'x', hi, lo}) 978 } 979 } 980 } 981 } 982 } 983 984 func isReadableDataType(typ *BufferType) bool { 985 return typ.Kind == BufferString || typ.Kind == BufferFilename || typ.Kind == BufferGlob 986 } 987 988 func isReadableData(data []byte) bool { 989 if len(data) == 0 { 990 return false 991 } 992 for _, v := range data { 993 if isPrintable(v) { 994 continue 995 } 996 switch v { 997 case 0, '\a', '\b', '\f', '\n', '\r', '\t', '\v': 998 continue 999 } 1000 return false 1001 } 1002 return true 1003 } 1004 1005 // Deserialize data, returning the data and whether it was encoded in Base64. 1006 func (p *parser) deserializeData() ([]byte, bool, error) { 1007 var data []byte 1008 if p.Char() == '"' { 1009 p.Parse('"') 1010 if p.Char() == '$' { 1011 // Read Base64 data. 1012 p.consume() 1013 var rawData []byte 1014 for !p.EOF() && p.Char() != '"' { 1015 v := p.consume() 1016 rawData = append(rawData, v) 1017 } 1018 p.Parse('"') 1019 decoded, err := image.DecodeB64(rawData) 1020 if err != nil { 1021 return nil, false, fmt.Errorf("data arg is corrupt: %w", err) 1022 } 1023 return decoded, true, nil 1024 } 1025 val := "" 1026 if p.Char() != '"' { 1027 val = p.Ident() 1028 } 1029 p.Parse('"') 1030 var err error 1031 data, err = hex.DecodeString(val) 1032 if err != nil { 1033 return nil, false, fmt.Errorf("data arg has bad value %q", val) 1034 } 1035 } else { 1036 if p.consume() != '\'' { 1037 return nil, false, fmt.Errorf("data arg does not start with \" nor with '") 1038 } 1039 for p.Char() != '\'' && p.Char() != 0 { 1040 v := p.consume() 1041 if v != '\\' { 1042 data = append(data, v) 1043 continue 1044 } 1045 v = p.consume() 1046 switch v { 1047 case 'x': 1048 hi := p.consume() 1049 lo := p.consume() 1050 b, ok := hexToByte(lo, hi) 1051 if !ok { 1052 return nil, false, fmt.Errorf("invalid hex \\x%v%v in data arg", hi, lo) 1053 } 1054 data = append(data, b) 1055 case 'a': 1056 data = append(data, '\a') 1057 case 'b': 1058 data = append(data, '\b') 1059 case 'f': 1060 data = append(data, '\f') 1061 case 'n': 1062 data = append(data, '\n') 1063 case 'r': 1064 data = append(data, '\r') 1065 case 't': 1066 data = append(data, '\t') 1067 case 'v': 1068 data = append(data, '\v') 1069 case '\'': 1070 data = append(data, '\'') 1071 case '"': 1072 data = append(data, '"') 1073 case '\\': 1074 data = append(data, '\\') 1075 default: 1076 return nil, false, fmt.Errorf("invalid \\%c escape sequence in data arg", v) 1077 } 1078 } 1079 p.Parse('\'') 1080 } 1081 return data, false, nil 1082 } 1083 1084 func isPrintable(v byte) bool { 1085 return v >= 0x20 && v < 0x7f 1086 } 1087 1088 func byteToHex(v byte) (lo, hi byte) { 1089 return toHexChar(v & 0xf), toHexChar(v >> 4) 1090 } 1091 1092 func hexToByte(lo, hi byte) (byte, bool) { 1093 h, ok1 := fromHexChar(hi) 1094 l, ok2 := fromHexChar(lo) 1095 return h<<4 + l, ok1 && ok2 1096 } 1097 1098 func toHexChar(v byte) byte { 1099 if v >= 16 { 1100 panic("bad hex char") 1101 } 1102 if v < 10 { 1103 return '0' + v 1104 } 1105 return 'a' + v - 10 1106 } 1107 1108 func fromHexChar(v byte) (byte, bool) { 1109 if v >= '0' && v <= '9' { 1110 return v - '0', true 1111 } 1112 if v >= 'a' && v <= 'f' { 1113 return v - 'a' + 10, true 1114 } 1115 return 0, false 1116 } 1117 1118 type parser struct { 1119 target *Target 1120 strict bool 1121 unsafe bool 1122 vars map[string]*ResultArg 1123 autos map[Arg]bool 1124 comment string 1125 1126 data []byte 1127 s string 1128 i int 1129 l int 1130 e error 1131 } 1132 1133 func newParser(target *Target, data []byte, strict, unsafe bool) *parser { 1134 p := &parser{ 1135 target: target, 1136 strict: strict, 1137 unsafe: unsafe, 1138 vars: make(map[string]*ResultArg), 1139 data: data, 1140 } 1141 return p 1142 } 1143 1144 func (p *parser) auto(arg Arg) Arg { 1145 if p.autos == nil { 1146 p.autos = make(map[Arg]bool) 1147 } 1148 p.autos[arg] = true 1149 return arg 1150 } 1151 1152 func (p *parser) fixupAutos(prog *Prog) { 1153 s := analyze(nil, nil, prog, nil) 1154 for _, c := range prog.Calls { 1155 p.target.assignSizesArray(c.Args, c.Meta.Args, p.autos) 1156 ForeachArg(c, func(arg Arg, _ *ArgCtx) { 1157 if !p.autos[arg] { 1158 return 1159 } 1160 delete(p.autos, arg) 1161 switch typ := arg.Type().(type) { 1162 case *ConstType: 1163 arg.(*ConstArg).Val = typ.Val 1164 _ = s 1165 case *PtrType: 1166 a := arg.(*PointerArg) 1167 a.Address = s.ma.alloc(nil, a.Res.Size(), a.Res.Type().Alignment()) 1168 default: 1169 panic(fmt.Sprintf("unsupported auto type %T", typ)) 1170 } 1171 }) 1172 } 1173 if len(p.autos) != 0 { 1174 panic(fmt.Sprintf("leftoever autos: %+v", p.autos)) 1175 } 1176 } 1177 1178 func (p *parser) fixupConditionals(prog *Prog) { 1179 for _, c := range prog.Calls { 1180 // Only overwrite transient union fields. 1181 c.setDefaultConditions(p.target, true) 1182 } 1183 } 1184 1185 func (p *parser) Scan() bool { 1186 if p.e != nil || len(p.data) == 0 { 1187 return false 1188 } 1189 nextLine := bytes.IndexByte(p.data, '\n') 1190 if nextLine != -1 { 1191 p.s = string(p.data[:nextLine]) 1192 p.data = p.data[nextLine+1:] 1193 } else { 1194 p.s = string(p.data) 1195 p.data = nil 1196 } 1197 p.i = 0 1198 p.l++ 1199 return true 1200 } 1201 1202 func (p *parser) Err() error { 1203 return p.e 1204 } 1205 1206 func (p *parser) EOF() bool { 1207 return p.i == len(p.s) 1208 } 1209 1210 func (p *parser) Char() byte { 1211 if p.e != nil { 1212 return 0 1213 } 1214 if p.EOF() { 1215 p.failf("unexpected eof") 1216 return 0 1217 } 1218 return p.s[p.i] 1219 } 1220 1221 func (p *parser) HasNext(str string) bool { 1222 if p.e != nil { 1223 return false 1224 } 1225 if len(p.s) < p.i+len(str) { 1226 return false 1227 } 1228 for i := 0; i < len(str); i++ { 1229 if p.s[p.i+i] != str[i] { 1230 return false 1231 } 1232 } 1233 return true 1234 } 1235 1236 func (p *parser) Parse(ch byte) { 1237 if p.e != nil { 1238 return 1239 } 1240 if p.EOF() { 1241 p.failf("want %s, got EOF", string(ch)) 1242 return 1243 } 1244 if p.s[p.i] != ch { 1245 p.failf("want '%v', got '%v'", string(ch), string(p.s[p.i])) 1246 return 1247 } 1248 p.i++ 1249 p.SkipWs() 1250 } 1251 1252 func (p *parser) consume() byte { 1253 if p.e != nil { 1254 return 0 1255 } 1256 if p.EOF() { 1257 p.failf("unexpected eof") 1258 return 0 1259 } 1260 v := p.s[p.i] 1261 p.i++ 1262 return v 1263 } 1264 1265 func (p *parser) SkipWs() { 1266 for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') { 1267 p.i++ 1268 } 1269 } 1270 1271 func (p *parser) Ident() string { 1272 i := p.i 1273 for p.i < len(p.s) && 1274 (p.s[p.i] >= 'a' && p.s[p.i] <= 'z' || 1275 p.s[p.i] >= 'A' && p.s[p.i] <= 'Z' || 1276 p.s[p.i] >= '0' && p.s[p.i] <= '9' || 1277 p.s[p.i] == '_' || p.s[p.i] == '$') { 1278 p.i++ 1279 } 1280 if i == p.i { 1281 p.failf("failed to parse identifier at pos %v", i) 1282 return "" 1283 } 1284 s := p.s[i:p.i] 1285 p.SkipWs() 1286 return s 1287 } 1288 1289 func (p *parser) failf(msg string, args ...interface{}) { 1290 if p.e == nil { 1291 p.e = fmt.Errorf("%v\nline #%v:%v: %v", fmt.Sprintf(msg, args...), p.l, p.i, 1292 highlightError(p.s, p.i)) 1293 } 1294 } 1295 1296 func (p *parser) strictFailf(msg string, args ...interface{}) { 1297 if p.strict { 1298 p.failf(msg, args...) 1299 } 1300 } 1301 1302 // CallSet returns a set of all calls in the program. 1303 // It does very conservative parsing and is intended to parse past/future serialization formats. 1304 func CallSet(data []byte) (map[string]struct{}, int, error) { 1305 calls := make(map[string]struct{}) 1306 ncalls := 0 1307 for len(data) > 0 { 1308 ln := data 1309 nextLine := bytes.IndexByte(data, '\n') 1310 if nextLine != -1 { 1311 ln = data[:nextLine] 1312 data = data[nextLine+1:] 1313 } else { 1314 data = nil 1315 } 1316 if len(ln) == 0 || ln[0] == '#' { 1317 continue 1318 } 1319 bracket := bytes.IndexByte(ln, '(') 1320 if bracket == -1 { 1321 return nil, 0, fmt.Errorf("line does not contain opening bracket") 1322 } 1323 call := ln[:bracket] 1324 if eq := bytes.IndexByte(call, '='); eq != -1 { 1325 eq++ 1326 for eq < len(call) && call[eq] == ' ' { 1327 eq++ 1328 } 1329 call = call[eq:] 1330 } 1331 if len(call) == 0 { 1332 return nil, 0, fmt.Errorf("call name is empty") 1333 } 1334 calls[string(call)] = struct{}{} 1335 ncalls++ 1336 } 1337 if len(calls) == 0 { 1338 return nil, 0, fmt.Errorf("program does not contain any calls") 1339 } 1340 return calls, ncalls, nil 1341 } 1342 1343 func highlightError(s string, offset int) string { 1344 return s[:offset] + "<<<!!ERROR!!>>>" + s[offset:] 1345 }