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