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  }