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  }