From 959ec07095ff4ec4423a1365e0f0f94844a77507 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 19 Oct 2016 16:20:37 +0200 Subject: sys: always use pointers to types Currently we store most types by value in sys.Type. This is somewhat counter-intuitive for C++ programmers, because one can't easily update the type object. Store pointers to type objects for all types. It also makes it easier to update types, e.g. adding paddings. --- sys/align.go | 10 +++--- sys/decl.go | 100 +++++++++++++++++++++++++++++------------------------------ 2 files changed, 55 insertions(+), 55 deletions(-) (limited to 'sys') diff --git a/sys/align.go b/sys/align.go index 055a433f8..1b1ea66ac 100644 --- a/sys/align.go +++ b/sys/align.go @@ -7,9 +7,9 @@ func initAlign() { var rec func(t Type) rec = func(t Type) { switch t1 := t.(type) { - case PtrType: + case *PtrType: rec(t1.Type) - case ArrayType: + case *ArrayType: rec(t1.Type) case *StructType: if !t1.padded { @@ -49,10 +49,10 @@ func addAlignment(t *StructType) { fields = append(fields, makePad(pad)) } fields = append(fields, f) - if at, ok := f.(ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) { + if at, ok := f.(*ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) { varLen = true } - if at, ok := f.(BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) { + if at, ok := f.(*BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) { varLen = true } if varLen && i != len(t.Fields)-1 { @@ -71,7 +71,7 @@ func addAlignment(t *StructType) { } func makePad(sz uintptr) Type { - return ConstType{ + return &ConstType{ TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: sz, Val: 0, diff --git a/sys/decl.go b/sys/decl.go index 89773b0dd..7f7c64c1d 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -29,7 +29,7 @@ type Type interface { } func IsPad(t Type) bool { - if ct, ok := t.(ConstType); ok && ct.IsPad { + if ct, ok := t.(*ConstType); ok && ct.IsPad { return true } return false @@ -40,15 +40,15 @@ type TypeCommon struct { IsOptional bool } -func (t TypeCommon) Name() string { +func (t *TypeCommon) Name() string { return t.TypeName } -func (t TypeCommon) Optional() bool { +func (t *TypeCommon) Optional() bool { return t.IsOptional } -func (t TypeCommon) Default() uintptr { +func (t *TypeCommon) Default() uintptr { return 0 } @@ -68,23 +68,23 @@ type ResourceType struct { Desc *ResourceDesc } -func (t ResourceType) Default() uintptr { +func (t *ResourceType) Default() uintptr { return t.Desc.Values[0] } -func (t ResourceType) SpecialValues() []uintptr { +func (t *ResourceType) SpecialValues() []uintptr { return t.Desc.Values } -func (t ResourceType) Size() uintptr { +func (t *ResourceType) Size() uintptr { return t.Desc.Type.Size() } -func (t ResourceType) Align() uintptr { +func (t *ResourceType) Align() uintptr { return t.Desc.Type.Align() } -func (t ResourceType) InnerType() Type { +func (t *ResourceType) InnerType() Type { return t } @@ -95,15 +95,15 @@ type FileoffType struct { File string } -func (t FileoffType) Size() uintptr { +func (t *FileoffType) Size() uintptr { return t.TypeSize } -func (t FileoffType) Align() uintptr { +func (t *FileoffType) Align() uintptr { return t.Size() } -func (t FileoffType) InnerType() Type { +func (t *FileoffType) InnerType() Type { return t } @@ -126,7 +126,7 @@ type BufferType struct { RangeEnd uintptr // for BufferBlobRange kind } -func (t BufferType) Size() uintptr { +func (t *BufferType) Size() uintptr { switch t.Kind { case BufferAlgType: return 14 @@ -142,11 +142,11 @@ func (t BufferType) Size() uintptr { } } -func (t BufferType) Align() uintptr { +func (t *BufferType) Align() uintptr { return 1 } -func (t BufferType) InnerType() Type { +func (t *BufferType) InnerType() Type { return t } @@ -154,15 +154,15 @@ type VmaType struct { TypeCommon } -func (t VmaType) Size() uintptr { +func (t *VmaType) Size() uintptr { return ptrSize } -func (t VmaType) Align() uintptr { +func (t *VmaType) Align() uintptr { return t.Size() } -func (t VmaType) InnerType() Type { +func (t *VmaType) InnerType() Type { return t } @@ -174,15 +174,15 @@ type LenType struct { Buf string } -func (t LenType) Size() uintptr { +func (t *LenType) Size() uintptr { return t.TypeSize } -func (t LenType) Align() uintptr { +func (t *LenType) Align() uintptr { return t.Size() } -func (t LenType) InnerType() Type { +func (t *LenType) InnerType() Type { return t } @@ -193,15 +193,15 @@ type FlagsType struct { Vals []uintptr } -func (t FlagsType) Size() uintptr { +func (t *FlagsType) Size() uintptr { return t.TypeSize } -func (t FlagsType) Align() uintptr { +func (t *FlagsType) Align() uintptr { return t.Size() } -func (t FlagsType) InnerType() Type { +func (t *FlagsType) InnerType() Type { return t } @@ -213,15 +213,15 @@ type ConstType struct { IsPad bool } -func (t ConstType) Size() uintptr { +func (t *ConstType) Size() uintptr { return t.TypeSize } -func (t ConstType) Align() uintptr { +func (t *ConstType) Align() uintptr { return t.Size() } -func (t ConstType) InnerType() Type { +func (t *ConstType) InnerType() Type { return t } @@ -231,15 +231,15 @@ type StrConstType struct { Val string } -func (t StrConstType) Size() uintptr { +func (t *StrConstType) Size() uintptr { return uintptr(len(t.Val)) } -func (t StrConstType) Align() uintptr { +func (t *StrConstType) Align() uintptr { return 1 } -func (t StrConstType) InnerType() Type { +func (t *StrConstType) InnerType() Type { return t } @@ -262,15 +262,15 @@ type IntType struct { RangeEnd int64 } -func (t IntType) Size() uintptr { +func (t *IntType) Size() uintptr { return t.TypeSize } -func (t IntType) Align() uintptr { +func (t *IntType) Align() uintptr { return t.Size() } -func (t IntType) InnerType() Type { +func (t *IntType) InnerType() Type { return t } @@ -278,15 +278,15 @@ type FilenameType struct { TypeCommon } -func (t FilenameType) Size() uintptr { +func (t *FilenameType) Size() uintptr { panic("filename size is not statically known") } -func (t FilenameType) Align() uintptr { +func (t *FilenameType) Align() uintptr { return 1 } -func (t FilenameType) InnerType() Type { +func (t *FilenameType) InnerType() Type { return t } @@ -305,18 +305,18 @@ type ArrayType struct { RangeEnd uintptr } -func (t ArrayType) Size() uintptr { +func (t *ArrayType) Size() uintptr { if t.RangeBegin == t.RangeEnd { return t.RangeBegin * t.Type.Size() } return 0 // for trailing embed arrays } -func (t ArrayType) Align() uintptr { +func (t *ArrayType) Align() uintptr { return t.Type.Align() } -func (t ArrayType) InnerType() Type { +func (t *ArrayType) InnerType() Type { return t } @@ -326,15 +326,15 @@ type PtrType struct { Dir Dir } -func (t PtrType) Size() uintptr { +func (t *PtrType) Size() uintptr { return ptrSize } -func (t PtrType) Align() uintptr { +func (t *PtrType) Align() uintptr { return t.Size() } -func (t PtrType) InnerType() Type { +func (t *PtrType) InnerType() Type { return t.Type.InnerType() } @@ -435,11 +435,11 @@ func resourceCtors(kind []string, precise bool) []*Call { seen := make(map[Type]bool) var checkArg func(typ Type, dir Dir) bool checkArg = func(typ Type, dir Dir) bool { - if resarg, ok := typ.(ResourceType); ok && dir != DirIn && isCompatibleResource(kind, resarg.Desc.Kind, precise) { + if resarg, ok := typ.(*ResourceType); ok && dir != DirIn && isCompatibleResource(kind, resarg.Desc.Kind, precise) { return true } switch typ1 := typ.(type) { - case ArrayType: + case *ArrayType: if checkArg(typ1.Type, dir) { return true } @@ -463,7 +463,7 @@ func resourceCtors(kind []string, precise bool) []*Call { return true } } - case PtrType: + case *PtrType: if checkArg(typ1.Type, typ1.Dir) { return true } @@ -524,19 +524,19 @@ func isCompatibleResource(dst, src []string, precise bool) bool { return true } -func (c *Call) InputResources() []ResourceType { - var resources []ResourceType +func (c *Call) InputResources() []*ResourceType { + var resources []*ResourceType seen := make(map[Type]bool) var checkArg func(typ Type, dir Dir) checkArg = func(typ Type, dir Dir) { switch typ1 := typ.(type) { - case ResourceType: + case *ResourceType: if dir != DirOut && !typ1.IsOptional { resources = append(resources, typ1) } - case ArrayType: + case *ArrayType: checkArg(typ1.Type, dir) - case PtrType: + case *PtrType: checkArg(typ1.Type, typ1.Dir) case *StructType: if seen[typ1] { -- cgit mrf-deployment From d3a93e8370682fa5231bc94faf11ed3681b2ac99 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 19 Oct 2016 14:41:46 +0200 Subject: sys: attach Dir to all types Dir is a static info, so we don't need to compute, propagate and attach it in prog whenever we generate/change programs. Attach Dir to all types. --- prog/analysis.go | 23 +++----- prog/encodingexec.go | 2 +- prog/mutation.go | 8 +-- prog/prio.go | 43 +-------------- prog/prog.go | 11 +--- prog/rand.go | 33 +++++------ prog/validation.go | 10 ++-- sys/decl.go | 153 +++++++++++++++++++++++---------------------------- sysgen/sysgen.go | 89 +++++++++++++++++------------- 9 files changed, 158 insertions(+), 214 deletions(-) (limited to 'sys') diff --git a/prog/analysis.go b/prog/analysis.go index d4ee93d10..24f02903c 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -52,11 +52,11 @@ func (s *state) analyze(c *Call) { foreachArgArray(&c.Args, c.Ret, func(arg, base *Arg, _ *[]*Arg) { switch typ := arg.Type.(type) { case *sys.FilenameType: - if arg.Kind == ArgData && arg.Dir != DirOut { + if arg.Kind == ArgData && arg.Type.Dir() != sys.DirOut { s.files[string(arg.Data)] = true } case *sys.ResourceType: - if arg.Dir != DirIn { + if arg.Type.Dir() != sys.DirIn { s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], arg) // TODO: negative PIDs and add them as well (that's process groups). } @@ -150,8 +150,8 @@ func foreachArg(c *Call, f func(arg, base *Arg, parent *[]*Arg)) { } func assignTypeAndDir(c *Call) error { - var rec func(arg *Arg, typ sys.Type, dir ArgDir) error - rec = func(arg *Arg, typ sys.Type, dir ArgDir) error { + var rec func(arg *Arg, typ sys.Type) error + rec = func(arg *Arg, typ sys.Type) error { if arg.Call != nil && arg.Call != c { panic(fmt.Sprintf("different call is already assigned: %p %p %v %v", arg.Call, c, arg.Call.Meta.Name, c.Meta.Name)) } @@ -162,41 +162,37 @@ func assignTypeAndDir(c *Call) error { arg.Type = typ switch arg.Kind { case ArgPointer: - arg.Dir = DirIn switch typ1 := typ.(type) { case *sys.PtrType: if arg.Res != nil { - if err := rec(arg.Res, typ1.Type, ArgDir(typ1.Dir)); err != nil { + if err := rec(arg.Res, typ1.Type); err != nil { return err } } } case ArgGroup: - arg.Dir = dir switch typ1 := typ.(type) { case *sys.StructType: if len(arg.Inner) != len(typ1.Fields) { return fmt.Errorf("wrong struct field count: %v, want %v", len(arg.Inner), len(typ1.Fields)) } for i, arg1 := range arg.Inner { - if err := rec(arg1, typ1.Fields[i], dir); err != nil { + if err := rec(arg1, typ1.Fields[i]); err != nil { return err } } case *sys.ArrayType: for _, arg1 := range arg.Inner { - if err := rec(arg1, typ1.Type, dir); err != nil { + if err := rec(arg1, typ1.Type); err != nil { return err } } } case ArgUnion: - arg.Dir = dir - if err := rec(arg.Option, arg.OptionType, dir); err != nil { + if err := rec(arg.Option, arg.OptionType); err != nil { return err } default: - arg.Dir = dir } return nil } @@ -204,7 +200,7 @@ func assignTypeAndDir(c *Call) error { if c.Meta == nil { panic("nil meta") } - if err := rec(arg, c.Meta.Args[i], DirIn); err != nil { + if err := rec(arg, c.Meta.Args[i]); err != nil { return err } } @@ -212,7 +208,6 @@ func assignTypeAndDir(c *Call) error { c.Ret = returnArg() c.Ret.Call = c c.Ret.Type = c.Meta.Ret - c.Ret.Dir = DirOut } return nil } diff --git a/prog/encodingexec.go b/prog/encodingexec.go index 239ef3514..f30cb7073 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -69,7 +69,7 @@ func (p *Prog) SerializeForExec() []byte { if arg1.Kind == ArgData && len(arg1.Data) == 0 { return } - if arg1.Dir != DirOut { + if arg1.Type.Dir() != sys.DirOut { w.write(ExecInstrCopyin) w.write(physicalAddr(arg) + w.args[arg1].Offset) w.writeArg(arg1) diff --git a/prog/mutation.go b/prog/mutation.go index 1b8be02c5..1c16a6347 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -61,7 +61,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { } switch a := arg.Type.(type) { case *sys.IntType, *sys.FlagsType, *sys.FileoffType, *sys.ResourceType, *sys.VmaType: - arg1, calls1 := r.generateArg(s, arg.Type, arg.Dir) + arg1, calls1 := r.generateArg(s, arg.Type) p.replaceArg(arg, arg1, calls1) case *sys.BufferType: switch a.Kind { @@ -123,7 +123,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { if count > uintptr(len(arg.Inner)) { var calls []*Call for count > uintptr(len(arg.Inner)) { - arg1, calls1 := r.generateArg(s, a.Type, arg.Dir) + arg1, calls1 := r.generateArg(s, a.Type) arg.Inner = append(arg.Inner, arg1) for _, c1 := range calls1 { calls = append(calls, c1) @@ -168,7 +168,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { optType = a.Options[r.Intn(len(a.Options))] } p.removeArg(arg.Option) - opt, calls := r.generateArg(s, optType, arg.Dir) + opt, calls := r.generateArg(s, optType) arg1 := unionArg(opt, optType) p.replaceArg(arg, arg1, calls) case *sys.LenType: @@ -344,7 +344,7 @@ func mutationArgs(c *Call) (args, bases []*Arg) { // Well, this is const. return } - if arg.Dir == DirOut { + if arg.Type.Dir() == sys.DirOut { return } if base != nil { diff --git a/prog/prio.go b/prog/prio.go index 3ac1eafe5..a21218dd1 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -50,7 +50,7 @@ func calcStaticPriorities() [][]float32 { uses[id][c.ID] = weight } } - foreachArgType(c, func(t sys.Type, d ArgDir) { + sys.ForeachType(c, func(t sys.Type) { switch a := t.(type) { case *sys.ResourceType: if a.Desc.Name == "pid" || a.Desc.Name == "uid" || a.Desc.Name == "gid" { @@ -196,47 +196,6 @@ func normalizePrio(prios [][]float32) { } } -func foreachArgType(meta *sys.Call, f func(sys.Type, ArgDir)) { - seen := make(map[sys.Type]bool) - var rec func(t sys.Type, dir ArgDir) - rec = func(t sys.Type, d ArgDir) { - f(t, d) - switch a := t.(type) { - case *sys.ArrayType: - rec(a.Type, d) - case *sys.PtrType: - rec(a.Type, ArgDir(a.Dir)) - case *sys.StructType: - if seen[a] { - return // prune recursion via pointers to structs/unions - } - seen[a] = true - for _, f := range a.Fields { - rec(f, d) - } - case *sys.UnionType: - if seen[a] { - return // prune recursion via pointers to structs/unions - } - seen[a] = true - for _, opt := range a.Options { - rec(opt, d) - } - case *sys.ResourceType, *sys.FileoffType, *sys.BufferType, - *sys.VmaType, *sys.LenType, *sys.FlagsType, *sys.ConstType, - *sys.StrConstType, *sys.IntType, *sys.FilenameType: - default: - panic("unknown type") - } - } - for _, t := range meta.Args { - rec(t, DirIn) - } - if meta.Ret != nil { - rec(meta.Ret, DirOut) - } -} - // ChooseTable allows to do a weighted choice of a syscall for a given syscall // based on call-to-call priorities and a set of enabled syscalls. type ChoiceTable struct { diff --git a/prog/prog.go b/prog/prog.go index aa5e1b86e..550b8416d 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -23,7 +23,6 @@ type Arg struct { Call *Call Type sys.Type Kind ArgKind - Dir ArgDir Val uintptr // value of ArgConst AddrPage uintptr // page index for ArgPointer address, page count for ArgPageSize AddrOffset int // page offset for ArgPointer address @@ -53,14 +52,6 @@ const ( ArgReturn // fake value denoting syscall return value ) -type ArgDir sys.Dir - -const ( - DirIn = ArgDir(sys.DirIn) - DirOut = ArgDir(sys.DirOut) - DirInOut = ArgDir(sys.DirInOut) -) - // Returns inner arg for PtrType args func (a *Arg) InnerArg(typ sys.Type) *Arg { switch typ1 := typ.(type) { @@ -177,7 +168,7 @@ func unionArg(opt *Arg, typ sys.Type) *Arg { } func returnArg() *Arg { - return &Arg{Kind: ArgReturn, Dir: DirOut} + return &Arg{Kind: ArgReturn} } func (p *Prog) insertBefore(c *Call, calls []*Call) { diff --git a/prog/rand.go b/prog/rand.go index 49726afcd..49c1ed193 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -600,7 +600,7 @@ func (r *randGen) generateCall(s *state, p *Prog) []*Call { func (r *randGen) generateParticularCall(s *state, meta *sys.Call) (calls []*Call) { c := &Call{Meta: meta} - c.Args, calls = r.generateArgs(s, meta.Args, DirIn) + c.Args, calls = r.generateArgs(s, meta.Args) calls = append(calls, c) for _, c1 := range calls { assignTypeAndDir(c1) @@ -609,13 +609,13 @@ func (r *randGen) generateParticularCall(s *state, meta *sys.Call) (calls []*Cal return calls } -func (r *randGen) generateArgs(s *state, types []sys.Type, dir ArgDir) ([]*Arg, []*Call) { +func (r *randGen) generateArgs(s *state, types []sys.Type) ([]*Arg, []*Call) { var calls []*Call args := make([]*Arg, len(types)) // Generate all args. Size args have the default value 0 for now. for i, typ := range types { - arg, calls1 := r.generateArg(s, typ, dir) + arg, calls1 := r.generateArg(s, typ) if arg == nil { panic(fmt.Sprintf("generated arg is nil for type '%v', types: %+v", typ.Name(), types)) } @@ -628,14 +628,15 @@ func (r *randGen) generateArgs(s *state, types []sys.Type, dir ArgDir) ([]*Arg, return args, calls } -func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir) (arg *Arg, calls []*Call) { - if dir == DirOut { +func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) { + if typ.Dir() == sys.DirOut { // No need to generate something interesting for output scalar arguments. // But we still need to generate the argument itself so that it can be referenced // in subsequent calls. For the same reason we do generate pointer/array/struct // output arguments (their elements can be referenced in subsequent calls). switch typ.(type) { - case *sys.IntType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, *sys.FileoffType, *sys.ResourceType: + case *sys.IntType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, + *sys.FileoffType, *sys.ResourceType, *sys.VmaType: return constArg(0), nil } } @@ -692,7 +693,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir) (arg *Arg, cal sz = r.randRange(int(a.RangeBegin), int(a.RangeEnd)) } data := make([]byte, sz) - if dir != DirOut { + if a.Dir() != sys.DirOut { for i := range data { data[i] = byte(r.Intn(256)) } @@ -706,7 +707,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir) (arg *Arg, cal return dataArg(data), nil case sys.BufferSockaddr: data := r.sockaddr(s) - if dir == DirOut { + if a.Dir() == sys.DirOut { for i := range data { data[i] = 0 } @@ -714,7 +715,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir) (arg *Arg, cal return dataArg(data), nil case sys.BufferAlgType: data := r.algType(s) - if dir == DirOut { + if a.Dir() == sys.DirOut { for i := range data { data[i] = 0 } @@ -722,7 +723,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir) (arg *Arg, cal return dataArg(data), nil case sys.BufferAlgName: data := r.algName(s) - if dir == DirOut { + if a.Dir() == sys.DirOut { for i := range data { data[i] = 0 } @@ -768,26 +769,26 @@ func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir) (arg *Arg, cal var inner []*Arg var calls []*Call for i := uintptr(0); i < count; i++ { - arg1, calls1 := r.generateArg(s, a.Type, dir) + arg1, calls1 := r.generateArg(s, a.Type) inner = append(inner, arg1) calls = append(calls, calls1...) } return groupArg(inner), calls case *sys.StructType: - if ctor := isSpecialStruct(a); ctor != nil && dir != DirOut { + if ctor := isSpecialStruct(a); ctor != nil && a.Dir() != sys.DirOut { arg, calls = ctor(r, s) return } - args, calls := r.generateArgs(s, a.Fields, dir) + args, calls := r.generateArgs(s, a.Fields) group := groupArg(args) return group, calls case *sys.UnionType: optType := a.Options[r.Intn(len(a.Options))] - opt, calls := r.generateArg(s, optType, dir) + opt, calls := r.generateArg(s, optType) return unionArg(opt, optType), calls case *sys.PtrType: - inner, calls := r.generateArg(s, a.Type, ArgDir(a.Dir)) - if ArgDir(a.Dir) == DirOut && inner == nil { + inner, calls := r.generateArg(s, a.Type) + if a.Dir() == sys.DirOut && inner == nil { // No data, but we should have got size. arg, calls1 := r.addr(s, inner.Size(a.Type), nil) calls = append(calls, calls1...) diff --git a/prog/validation.go b/prog/validation.go index ec407721a..998581e28 100644 --- a/prog/validation.go +++ b/prog/validation.go @@ -57,7 +57,7 @@ func (c *Call) validate(ctx *validCtx) error { if arg.Type.Name() != typ.Name() { return fmt.Errorf("syscall %v: arg '%v' type mismatch", c.Meta.Name, typ.Name()) } - if arg.Dir == DirOut { + if arg.Type.Dir() == sys.DirOut { if arg.Val != 0 || arg.AddrPage != 0 || arg.AddrOffset != 0 { return fmt.Errorf("syscall %v: output arg '%v' has data", c.Meta.Name, typ.Name()) } @@ -73,7 +73,7 @@ func (c *Call) validate(ctx *validCtx) error { case ArgResult: case ArgReturn: case ArgConst: - if arg.Dir == DirOut && arg.Val != 0 { + if arg.Type.Dir() == sys.DirOut && arg.Val != 0 { return fmt.Errorf("syscall %v: out resource arg '%v' has bad const value %v", c.Meta.Name, typ.Name(), arg.Val) } default: @@ -112,9 +112,6 @@ func (c *Call) validate(ctx *validCtx) error { return fmt.Errorf("syscall %v: result arg '%v' has broken link (%+v)", c.Meta.Name, typ.Name(), arg.Res.Uses) } case ArgPointer: - if arg.Dir != DirIn { - return fmt.Errorf("syscall %v: pointer arg '%v' has output direction", c.Meta.Name, typ.Name()) - } switch typ1 := typ.(type) { case *sys.VmaType: if arg.Res != nil { @@ -124,6 +121,9 @@ func (c *Call) validate(ctx *validCtx) error { return fmt.Errorf("syscall %v: vma arg '%v' has size 0", c.Meta.Name, typ.Name()) } case *sys.PtrType: + if arg.Type.Dir() != sys.DirIn { + return fmt.Errorf("syscall %v: pointer arg '%v' has output direction", c.Meta.Name, typ.Name()) + } if arg.Res == nil && !typ.Optional() { return fmt.Errorf("syscall %v: non optional pointer arg '%v' is nil", c.Meta.Name, typ.Name()) } diff --git a/sys/decl.go b/sys/decl.go index 7f7c64c1d..e19e4c028 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -19,8 +19,17 @@ type Call struct { Ret Type } +type Dir int + +const ( + DirIn Dir = iota + DirOut + DirInOut +) + type Type interface { Name() string + Dir() Dir Optional() bool Default() uintptr Size() uintptr @@ -37,6 +46,7 @@ func IsPad(t Type) bool { type TypeCommon struct { TypeName string + ArgDir Dir IsOptional bool } @@ -52,6 +62,10 @@ func (t *TypeCommon) Default() uintptr { return 0 } +func (t TypeCommon) Dir() Dir { + return t.ArgDir +} + const ( InvalidFD = ^uintptr(0) ) @@ -323,7 +337,6 @@ func (t *ArrayType) InnerType() Type { type PtrType struct { TypeCommon Type Type - Dir Dir } func (t *PtrType) Size() uintptr { @@ -407,14 +420,6 @@ func (t *UnionType) InnerType() Type { return t } -type Dir int - -const ( - DirIn Dir = iota - DirOut - DirInOut -) - var ctors = make(map[string][]*Call) // ResourceConstructors returns a list of calls that can create a resource of the given kind. @@ -431,56 +436,20 @@ func initResources() { func resourceCtors(kind []string, precise bool) []*Call { // Find calls that produce the necessary resources. var metas []*Call - // Recurse into arguments to see if there is an out/inout arg of necessary type. - seen := make(map[Type]bool) - var checkArg func(typ Type, dir Dir) bool - checkArg = func(typ Type, dir Dir) bool { - if resarg, ok := typ.(*ResourceType); ok && dir != DirIn && isCompatibleResource(kind, resarg.Desc.Kind, precise) { - return true - } - switch typ1 := typ.(type) { - case *ArrayType: - if checkArg(typ1.Type, dir) { - return true - } - case *StructType: - if seen[typ1] { - return false // prune recursion via pointers to structs/unions - } - seen[typ1] = true - for _, fld := range typ1.Fields { - if checkArg(fld, dir) { - return true - } - } - case *UnionType: - if seen[typ1] { - return false // prune recursion via pointers to structs/unions - } - seen[typ1] = true - for _, opt := range typ1.Options { - if checkArg(opt, dir) { - return true - } - } - case *PtrType: - if checkArg(typ1.Type, typ1.Dir) { - return true - } - } - return false - } for _, meta := range Calls { + // Recurse into arguments to see if there is an out/inout arg of necessary type. ok := false - for _, arg := range meta.Args { - if checkArg(arg, DirIn) { - ok = true - break + ForeachType(meta, func(typ Type) { + if ok { + return } - } - if !ok && meta.Ret != nil && checkArg(meta.Ret, DirOut) { - ok = true - } + switch typ1 := typ.(type) { + case *ResourceType: + if typ1.Dir() != DirIn && isCompatibleResource(kind, typ1.Desc.Kind, precise) { + ok = true + } + } + }) if ok { metas = append(metas, meta) } @@ -526,39 +495,14 @@ func isCompatibleResource(dst, src []string, precise bool) bool { func (c *Call) InputResources() []*ResourceType { var resources []*ResourceType - seen := make(map[Type]bool) - var checkArg func(typ Type, dir Dir) - checkArg = func(typ Type, dir Dir) { + ForeachType(c, func(typ Type) { switch typ1 := typ.(type) { case *ResourceType: - if dir != DirOut && !typ1.IsOptional { + if typ1.Dir() != DirOut && !typ1.IsOptional { resources = append(resources, typ1) } - case *ArrayType: - checkArg(typ1.Type, dir) - case *PtrType: - checkArg(typ1.Type, typ1.Dir) - case *StructType: - if seen[typ1] { - return // prune recursion via pointers to structs/unions - } - seen[typ1] = true - for _, fld := range typ1.Fields { - checkArg(fld, dir) - } - case *UnionType: - if seen[typ1] { - return // prune recursion via pointers to structs/unions - } - seen[typ1] = true - for _, opt := range typ1.Options { - checkArg(opt, dir) - } } - } - for _, arg := range c.Args { - checkArg(arg, DirIn) - } + }) return resources } @@ -598,6 +542,47 @@ func TransitivelyEnabledCalls(enabled map[*Call]bool) map[*Call]bool { return supported } +func ForeachType(meta *Call, f func(Type)) { + seen := make(map[Type]bool) + var rec func(t Type) + rec = func(t Type) { + f(t) + switch a := t.(type) { + case *PtrType: + rec(a.Type) + case *ArrayType: + rec(a.Type) + case *StructType: + if seen[a] { + return // prune recursion via pointers to structs/unions + } + seen[a] = true + for _, f := range a.Fields { + rec(f) + } + case *UnionType: + if seen[a] { + return // prune recursion via pointers to structs/unions + } + seen[a] = true + for _, opt := range a.Options { + rec(opt) + } + case *ResourceType, *FileoffType, *BufferType, + *VmaType, *LenType, *FlagsType, *ConstType, + *StrConstType, *IntType, *FilenameType: + default: + panic("unknown type") + } + } + for _, t := range meta.Args { + rec(t) + } + if meta.Ret != nil { + rec(meta.Ret) + } +} + var ( Calls []*Call CallCount int diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index cdc79794c..c66f2af7a 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -162,7 +162,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W fmt.Fprintf(out, "func() { Calls = append(Calls, &Call{Name: \"%v\", CallName: \"%v\"", s.Name, s.CallName) if len(s.Ret) != 0 { fmt.Fprintf(out, ", Ret: ") - generateArg("", "ret", s.Ret[0], s.Ret[1:], desc, consts, true, false, out) + generateArg("", "ret", s.Ret[0], "out", s.Ret[1:], desc, consts, true, false, out) } fmt.Fprintf(out, ", Args: []Type{") for i, a := range s.Args { @@ -170,7 +170,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W fmt.Fprintf(out, ", ") } logf(5, " generate description for arg %v", i) - generateArg("", a[0], a[1], a[2:], desc, consts, true, false, out) + generateArg("", a[0], a[1], "in", a[2:], desc, consts, true, false, out) } if skipCurrentSyscall != "" { logf(0, "unsupported syscall: %v due to %v", s.Name, skipCurrentSyscall) @@ -230,7 +230,7 @@ func generateResources(desc *Description, consts map[string]uint64, out io.Write } } fmt.Fprintf(out, "\"%v\": &ResourceDesc{Name: \"%v\", Type: ", name, name) - generateArg("", "resource-type", underlying, nil, desc, consts, true, true, out) + generateArg("", "resource-type", underlying, "inout", nil, desc, consts, true, true, out) fmt.Fprintf(out, ", Kind: []string{") for i, k := range kind { if i != 0 { @@ -253,11 +253,21 @@ func generateResources(desc *Description, consts map[string]uint64, out io.Write fmt.Fprintf(out, "}\n") } -func generateStructEntry(str Struct, key string, name string, out io.Writer) { +type structKey struct { + name string + field string + dir string +} + +func generateStructEntry(str Struct, key structKey, out io.Writer) { typ := "StructType" if str.IsUnion { typ = "UnionType" } + name := key.field + if name == "" { + name = key.name + } packed := "" if str.Packed { packed = ", packed: true" @@ -270,11 +280,11 @@ func generateStructEntry(str Struct, key string, name string, out io.Writer) { if str.Align != 0 { align = fmt.Sprintf(", align: %v", str.Align) } - fmt.Fprintf(out, "\"%v\": &%v{TypeCommon: TypeCommon{TypeName: \"%v\", IsOptional: %v} %v %v %v},\n", - key, typ, name, false, packed, align, varlen) + fmt.Fprintf(out, "\"%v\": &%v{TypeCommon: TypeCommon{TypeName: \"%v\", ArgDir: %v, IsOptional: %v} %v %v %v},\n", + key, typ, name, fmtDir(key.dir), false, packed, align, varlen) } -func generateStructFields(str Struct, key string, desc *Description, consts map[string]uint64, out io.Writer) { +func generateStructFields(str Struct, key structKey, desc *Description, consts map[string]uint64, out io.Writer) { typ := "StructType" fields := "Fields" if str.IsUnion { @@ -284,7 +294,7 @@ func generateStructFields(str Struct, key string, desc *Description, consts map[ fmt.Fprintf(out, "{ s := Structs[\"%v\"].(*%v)\n", key, typ) for _, a := range str.Flds { fmt.Fprintf(out, "s.%v = append(s.%v, ", fields, fields) - generateArg(str.Name, a[0], a[1], a[2:], desc, consts, false, true, out) + generateArg(str.Name, a[0], a[1], key.dir, a[2:], desc, consts, false, true, out) fmt.Fprintf(out, ")\n") } fmt.Fprintf(out, "}\n") @@ -301,24 +311,23 @@ func generateStructs(desc *Description, consts map[string]uint64, out io.Writer) // for each field indexed by the name of the parent struct and the // field name. - structMap := make(map[string]Struct) + structMap := make(map[structKey]Struct) for _, str := range desc.Structs { - if _, ok := structMap[str.Name]; ok { - failf("two structs with the same name '%v'", str.Name) + for _, dir := range []string{"in", "out", "inout"} { + structMap[structKey{str.Name, "", dir}] = str } - structMap[str.Name] = str for _, a := range str.Flds { if innerStr, ok := desc.Structs[a[1]]; ok { - structMap[fmt.Sprintf("%v-%v", str.Name, a[0])] = innerStr + for _, dir := range []string{"in", "out", "inout"} { + structMap[structKey{a[1], a[0], dir}] = innerStr + } } } } fmt.Fprintf(out, "var Structs = map[string]Type{\n") for key, str := range structMap { - keyParts := strings.Split(key, "-") - name := keyParts[len(keyParts)-1] - generateStructEntry(str, key, name, out) + generateStructEntry(str, key, out) } fmt.Fprintf(out, "}\n") @@ -351,7 +360,7 @@ func parseRange(buffer string, consts map[string]uint64) (string, string) { } func generateArg( - parent, name, typ string, + parent, name, typ, dir string, a []string, desc *Description, consts map[string]uint64, @@ -369,7 +378,7 @@ func generateArg( } } common := func() string { - return fmt.Sprintf("TypeCommon: TypeCommon{TypeName: %v, IsOptional: %v}", name, opt) + return fmt.Sprintf("TypeCommon: TypeCommon{TypeName: %v, ArgDir: %v, IsOptional: %v}", name, fmtDir(dir), opt) } canBeArg := false switch typ { @@ -393,25 +402,28 @@ func generateArg( if want := 1; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - commonHdr := common() + ptrCommonHdr := common() + dir = a[0] opt = false - fmt.Fprintf(out, "&PtrType{%v, Dir: %v, Type: &BufferType{%v, Kind: BufferBlobRand}}", commonHdr, fmtDir(a[0]), common()) + fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferBlobRand}}", ptrCommonHdr, common()) case "string": canBeArg = true if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - commonHdr := common() + ptrCommonHdr := common() + dir = "in" opt = false - fmt.Fprintf(out, "&PtrType{%v, Dir: %v, Type: &BufferType{%v, Kind: BufferString}}", commonHdr, fmtDir("in"), common()) + fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferString}}", ptrCommonHdr, common()) case "filesystem": canBeArg = true if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - commonHdr := common() + ptrCommonHdr := common() + dir = "in" opt = false - fmt.Fprintf(out, "&PtrType{%v, Dir: %v, Type: &BufferType{%v, Kind: BufferFilesystem}}", commonHdr, fmtDir("in"), common()) + fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferFilesystem}}", ptrCommonHdr, common()) case "sockaddr": if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) @@ -500,7 +512,10 @@ func generateArg( if want := 1; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - fmt.Fprintf(out, "&PtrType{%v, Dir: %v, Type: &StrConstType{%v, Val: \"%v\"}}", common(), fmtDir("in"), common(), a[0]+"\\x00") + ptrCommonHdr := common() + dir = "in" + opt = false + fmt.Fprintf(out, "&PtrType{%v, Type: &StrConstType{%v, Val: \"%v\"}}", ptrCommonHdr, common(), a[0]+"\\x00") case "int8", "int16", "int32", "int64", "intptr", "int16be", "int32be", "int64be", "intptrbe": canBeArg = true size, bigEndian := decodeIntType(typ) @@ -534,9 +549,10 @@ func generateArg( if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - commonHdr := common() + ptrCommonHdr := common() + dir = "in" opt = false - fmt.Fprintf(out, "&PtrType{%v, Dir: DirIn, Type: &FilenameType{%v}}", commonHdr, common()) + fmt.Fprintf(out, "&PtrType{%v, Type: &FilenameType{%v}}", ptrCommonHdr, common()) case "array": if len(a) != 1 && len(a) != 2 { failf("wrong number of arguments for %v arg %v, want 1 or 2, got %v", typ, name, len(a)) @@ -545,14 +561,14 @@ func generateArg( if a[0] == "int8" { fmt.Fprintf(out, "&BufferType{%v, Kind: BufferBlobRand}", common()) } else { - fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], desc, consts)) + fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], dir, desc, consts)) } } else { begin, end := parseRange(a[1], consts) if a[0] == "int8" { fmt.Fprintf(out, "&BufferType{%v, Kind: BufferBlobRange, RangeBegin: %v, RangeEnd: %v}", common(), begin, end) } else { - fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], desc, consts), begin, end) + fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], dir, desc, consts), begin, end) } } case "ptr": @@ -560,11 +576,12 @@ func generateArg( if want := 2; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - fmt.Fprintf(out, "&PtrType{%v, Type: %v, Dir: %v}", common(), generateType(a[1], desc, consts), fmtDir(a[0])) + dir = "in" + fmt.Fprintf(out, "&PtrType{%v, Type: %v}", common(), generateType(a[1], a[0], desc, consts)) default: if strings.HasPrefix(typ, "unnamed") { if inner, ok := desc.Unnamed[typ]; ok { - generateArg("", "", inner[0], inner[1:], desc, consts, false, isField, out) + generateArg("", "", inner[0], dir, inner[1:], desc, consts, false, isField, out) } else { failf("unknown unnamed type '%v'", typ) } @@ -572,11 +589,7 @@ func generateArg( if len(a) != 0 { failf("struct '%v' has args", typ) } - if parent == "" { - fmt.Fprintf(out, "Structs[\"%v\"]", typ) - } else { - fmt.Fprintf(out, "Structs[\"%v-%v\"]", parent, origName) - } + fmt.Fprintf(out, "Structs[\"%v\"]", structKey{typ, origName, dir}) } else if _, ok := desc.Resources[typ]; ok { if len(a) != 0 { failf("resource '%v' has args", typ) @@ -592,9 +605,9 @@ func generateArg( } } -func generateType(typ string, desc *Description, consts map[string]uint64) string { +func generateType(typ, dir string, desc *Description, consts map[string]uint64) string { buf := new(bytes.Buffer) - generateArg("", "", typ, nil, desc, consts, false, true, buf) + generateArg("", "", typ, dir, nil, desc, consts, false, true, buf) return buf.String() } -- cgit mrf-deployment From b40d502736438fcd899cda22e92fd0a159eecf4f Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 29 Oct 2016 23:42:36 +0200 Subject: prog: remote Type argument from Arg.Size/Value They are not necessary since we now always have types attached to args. Also remove sys.Type.InnerType as it is not necessary now as well. --- prog/analysis.go | 21 +++++++++---------- prog/encodingexec.go | 14 ++++++------- prog/mutation.go | 8 ++++---- prog/prog.go | 39 ++++++++++++++++++----------------- prog/rand.go | 4 ++-- sys/decl.go | 57 ---------------------------------------------------- 6 files changed, 41 insertions(+), 102 deletions(-) (limited to 'sys') diff --git a/prog/analysis.go b/prog/analysis.go index f5219895d..98973d4c7 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -160,12 +160,12 @@ func generateSize(arg *Arg, lenType *sys.LenType) *Arg { return pageSizeArg(lenType, arg.AddrPagesNum, 0) case *sys.ArrayType: if lenType.ByteSize { - return constArg(lenType, arg.Size(arg.Type)) + return constArg(lenType, arg.Size()) } else { return constArg(lenType, uintptr(len(arg.Inner))) } default: - return constArg(lenType, arg.Size(arg.Type)) + return constArg(lenType, arg.Size()) } } @@ -174,22 +174,19 @@ func assignSizes(args []*Arg) { argsMap := make(map[string]*Arg) var parentSize uintptr for _, arg := range args { - parentSize += arg.Size(arg.Type) + parentSize += arg.Size() if sys.IsPad(arg.Type) { continue } - argsMap[arg.Type.Name()] = arg.InnerArg(arg.Type) + argsMap[arg.Type.Name()] = arg } // Fill in size arguments. for _, arg := range args { - if typ, ok := arg.Type.InnerType().(*sys.LenType); ok { - arg = arg.InnerArg(arg.Type) - if arg == nil { - // Pointer to optional len field, no need to fill in value. - continue - } - + if arg = arg.InnerArg(); arg == nil { + continue // Pointer to optional len field, no need to fill in value. + } + if typ, ok := arg.Type.(*sys.LenType); ok { if typ.Buf == "parent" { arg.Val = parentSize continue @@ -201,7 +198,7 @@ func assignSizes(args []*Arg) { typ.Name(), typ.Buf, argsMap)) } - *arg = *generateSize(buf, typ) + *arg = *generateSize(buf.InnerArg(), typ) } } } diff --git a/prog/encodingexec.go b/prog/encodingexec.go index f30cb7073..4c2cd2524 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -46,7 +46,7 @@ func (p *Prog) SerializeForExec() []byte { w.args[base] = &argInfo{} } w.args[arg] = &argInfo{Offset: w.args[base].CurSize} - w.args[base].CurSize += arg.Size(arg.Type) + w.args[base].CurSize += arg.Size() }) // Generate copyin instructions that fill in data into pointer arguments. foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { @@ -105,7 +105,7 @@ func (p *Prog) SerializeForExec() []byte { instrSeq++ w.write(ExecInstrCopyout) w.write(physicalAddr(base) + info.Offset) - w.write(arg.Size(arg.Type)) + w.write(arg.Size()) default: panic("bad arg kind in copyout") } @@ -147,21 +147,21 @@ func (w *execContext) writeArg(arg *Arg) { switch arg.Kind { case ArgConst: w.write(ExecArgConst) - w.write(arg.Size(arg.Type)) - w.write(arg.Value(arg.Type)) + w.write(arg.Size()) + w.write(arg.Value()) case ArgResult: w.write(ExecArgResult) - w.write(arg.Size(arg.Type)) + w.write(arg.Size()) w.write(w.args[arg.Res].Idx) w.write(arg.OpDiv) w.write(arg.OpAdd) case ArgPointer: w.write(ExecArgConst) - w.write(arg.Size(arg.Type)) + w.write(arg.Size()) w.write(physicalAddr(arg)) case ArgPageSize: w.write(ExecArgConst) - w.write(arg.Size(arg.Type)) + w.write(arg.Size()) w.write(arg.AddrPage * pageSize) case ArgData: w.write(ExecArgData) diff --git a/prog/mutation.go b/prog/mutation.go index c014381d7..da8ad83bf 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -57,7 +57,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { if base.Kind != ArgPointer || base.Res == nil { panic("bad base arg") } - baseSize = base.Res.Size(base.Res.Type) + baseSize = base.Res.Size() } switch a := arg.Type.(type) { case *sys.IntType, *sys.FlagsType, *sys.FileoffType, *sys.ResourceType, *sys.VmaType: @@ -146,7 +146,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { // TODO: we don't know size for out args size := uintptr(1) if arg.Res != nil { - size = arg.Res.Size(arg.Res.Type) + size = arg.Res.Size() } arg1, calls1 := r.addr(s, a, size, arg.Res) p.replaceArg(c, arg, arg1, calls1) @@ -178,8 +178,8 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { } // Update base pointer if size has increased. - if base != nil && baseSize < base.Res.Size(base.Res.Type) { - arg1, calls1 := r.addr(s, base.Type, base.Res.Size(base.Res.Type), base.Res) + if base != nil && baseSize < base.Res.Size() { + arg1, calls1 := r.addr(s, base.Type, base.Res.Size(), base.Res) for _, c1 := range calls1 { sanitizeCall(c1) } diff --git a/prog/prog.go b/prog/prog.go index 47c99b1d5..26e7dc0b8 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -52,17 +52,16 @@ const ( ) // Returns inner arg for PtrType args -func (a *Arg) InnerArg(typ sys.Type) *Arg { - switch typ1 := typ.(type) { +func (a *Arg) InnerArg() *Arg { + switch typ := a.Type.(type) { case *sys.PtrType: if a.Res == nil { - if typ.Optional() { - return nil - } else { - panic(fmt.Sprintf("non-optional pointer is nil\narg: %+v\ntype: %+v", a, typ1)) + if !typ.Optional() { + panic(fmt.Sprintf("non-optional pointer is nil\narg: %+v\ntype: %+v", a, typ)) } + return nil } else { - return a.Res.InnerArg(typ1.Type) + return a.Res.InnerArg() } default: return a @@ -86,24 +85,24 @@ func encodeValue(value, size uintptr, bigEndian bool) uintptr { } // Returns value taking endianness into consideration. -func (a *Arg) Value(typ sys.Type) uintptr { - switch t := typ.(type) { +func (a *Arg) Value() uintptr { + switch typ := a.Type.(type) { case *sys.IntType: - return encodeValue(a.Val, t.Size(), t.BigEndian) + return encodeValue(a.Val, typ.Size(), typ.BigEndian) case *sys.ConstType: - return encodeValue(a.Val, t.Size(), t.BigEndian) + return encodeValue(a.Val, typ.Size(), typ.BigEndian) case *sys.FlagsType: - return encodeValue(a.Val, t.Size(), t.BigEndian) + return encodeValue(a.Val, typ.Size(), typ.BigEndian) case *sys.LenType: - return encodeValue(a.Val, t.Size(), t.BigEndian) + return encodeValue(a.Val, typ.Size(), typ.BigEndian) case *sys.FileoffType: - return encodeValue(a.Val, t.Size(), t.BigEndian) + return encodeValue(a.Val, typ.Size(), typ.BigEndian) } return a.Val } -func (a *Arg) Size(typ sys.Type) uintptr { - switch typ1 := typ.(type) { +func (a *Arg) Size() uintptr { + switch typ := a.Type.(type) { case *sys.IntType, *sys.LenType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, *sys.FileoffType, *sys.ResourceType, *sys.VmaType, *sys.PtrType: return typ.Size() @@ -113,16 +112,16 @@ func (a *Arg) Size(typ sys.Type) uintptr { return uintptr(len(a.Data)) case *sys.StructType: var size uintptr - for i, f := range typ1.Fields { - size += a.Inner[i].Size(f) + for _, fld := range a.Inner { + size += fld.Size() } return size case *sys.UnionType: - return a.Option.Size(a.OptionType) + return a.Option.Size() case *sys.ArrayType: var size uintptr for _, in := range a.Inner { - size += in.Size(typ1.Type) + size += in.Size() } return size default: diff --git a/prog/rand.go b/prog/rand.go index 62cd81acc..99fcd96a5 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -817,7 +817,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) inner, calls := r.generateArg(s, a.Type) if a.Dir() == sys.DirOut && inner == nil { // No data, but we should have got size. - arg, calls1 := r.addr(s, a, inner.Size(a.Type), nil) + arg, calls1 := r.addr(s, a, inner.Size(), nil) calls = append(calls, calls1...) return arg, calls } @@ -829,7 +829,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) arg = pointerArg(a, addr.AddrPage, addr.AddrOffset, addr.AddrPagesNum, inner) return arg, calls } - arg, calls1 := r.addr(s, a, inner.Size(a.Type), inner) + arg, calls1 := r.addr(s, a, inner.Size(), inner) calls = append(calls, calls1...) return arg, calls case *sys.LenType: diff --git a/sys/decl.go b/sys/decl.go index e19e4c028..66dc4370a 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -34,7 +34,6 @@ type Type interface { Default() uintptr Size() uintptr Align() uintptr - InnerType() Type // returns inner type for PtrType } func IsPad(t Type) bool { @@ -98,10 +97,6 @@ func (t *ResourceType) Align() uintptr { return t.Desc.Type.Align() } -func (t *ResourceType) InnerType() Type { - return t -} - type FileoffType struct { TypeCommon TypeSize uintptr @@ -117,10 +112,6 @@ func (t *FileoffType) Align() uintptr { return t.Size() } -func (t *FileoffType) InnerType() Type { - return t -} - type BufferKind int const ( @@ -160,10 +151,6 @@ func (t *BufferType) Align() uintptr { return 1 } -func (t *BufferType) InnerType() Type { - return t -} - type VmaType struct { TypeCommon } @@ -176,10 +163,6 @@ func (t *VmaType) Align() uintptr { return t.Size() } -func (t *VmaType) InnerType() Type { - return t -} - type LenType struct { TypeCommon TypeSize uintptr @@ -196,10 +179,6 @@ func (t *LenType) Align() uintptr { return t.Size() } -func (t *LenType) InnerType() Type { - return t -} - type FlagsType struct { TypeCommon TypeSize uintptr @@ -215,10 +194,6 @@ func (t *FlagsType) Align() uintptr { return t.Size() } -func (t *FlagsType) InnerType() Type { - return t -} - type ConstType struct { TypeCommon TypeSize uintptr @@ -235,10 +210,6 @@ func (t *ConstType) Align() uintptr { return t.Size() } -func (t *ConstType) InnerType() Type { - return t -} - type StrConstType struct { TypeCommon TypeSize uintptr @@ -253,10 +224,6 @@ func (t *StrConstType) Align() uintptr { return 1 } -func (t *StrConstType) InnerType() Type { - return t -} - type IntKind int const ( @@ -284,10 +251,6 @@ func (t *IntType) Align() uintptr { return t.Size() } -func (t *IntType) InnerType() Type { - return t -} - type FilenameType struct { TypeCommon } @@ -300,10 +263,6 @@ func (t *FilenameType) Align() uintptr { return 1 } -func (t *FilenameType) InnerType() Type { - return t -} - type ArrayKind int const ( @@ -330,10 +289,6 @@ func (t *ArrayType) Align() uintptr { return t.Type.Align() } -func (t *ArrayType) InnerType() Type { - return t -} - type PtrType struct { TypeCommon Type Type @@ -347,10 +302,6 @@ func (t *PtrType) Align() uintptr { return t.Size() } -func (t *PtrType) InnerType() Type { - return t.Type.InnerType() -} - type StructType struct { TypeCommon Fields []Type @@ -383,10 +334,6 @@ func (t *StructType) Align() uintptr { return align } -func (t *StructType) InnerType() Type { - return t -} - type UnionType struct { TypeCommon Options []Type @@ -416,10 +363,6 @@ func (t *UnionType) Align() uintptr { return align } -func (t *UnionType) InnerType() Type { - return t -} - var ctors = make(map[string][]*Call) // ResourceConstructors returns a list of calls that can create a resource of the given kind. -- cgit mrf-deployment From 8b731ed4b705c3049af917f1c01db5b4a0bc59a1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 29 Oct 2016 15:55:35 -0600 Subject: sys: replace FilenameType with BufferType{Kind: BufferFilename} FilenameType is effectively a buffer, there is no need for a separate type. --- prog/analysis.go | 13 +++++++------ prog/mutation.go | 5 ++--- prog/prio.go | 4 ++-- prog/prog.go | 2 -- prog/rand.go | 6 +++--- prog/validation.go | 6 ------ sys/decl.go | 15 ++------------- sysgen/sysgen.go | 2 +- 8 files changed, 17 insertions(+), 36 deletions(-) (limited to 'sys') diff --git a/prog/analysis.go b/prog/analysis.go index 98973d4c7..4bf6506f1 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -51,18 +51,19 @@ func newState(ct *ChoiceTable) *state { func (s *state) analyze(c *Call) { foreachArgArray(&c.Args, c.Ret, func(arg, base *Arg, _ *[]*Arg) { switch typ := arg.Type.(type) { - case *sys.FilenameType: - if arg.Kind == ArgData && arg.Type.Dir() != sys.DirOut { - s.files[string(arg.Data)] = true - } case *sys.ResourceType: if arg.Type.Dir() != sys.DirIn { s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], arg) // TODO: negative PIDs and add them as well (that's process groups). } case *sys.BufferType: - if typ.Kind == sys.BufferString && arg.Kind == ArgData && len(arg.Data) != 0 { - s.strings[string(arg.Data)] = true + if arg.Type.Dir() != sys.DirOut && arg.Kind == ArgData && len(arg.Data) != 0 { + switch typ.Kind { + case sys.BufferString: + s.strings[string(arg.Data)] = true + case sys.BufferFilename: + s.files[string(arg.Data)] = true + } } } }) diff --git a/prog/mutation.go b/prog/mutation.go index da8ad83bf..166d5a065 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -93,6 +93,8 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { } case sys.BufferFilesystem: arg.Data = r.filesystem(s) + case sys.BufferFilename: + arg.Data = []byte(r.filename(s)) case sys.BufferSockaddr: arg.Data = r.sockaddr(s) case sys.BufferAlgType: @@ -102,9 +104,6 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { default: panic("unknown buffer kind") } - case *sys.FilenameType: - filename := r.filename(s) - arg.Data = []byte(filename) case *sys.ArrayType: count := uintptr(0) switch a.Kind { diff --git a/prog/prio.go b/prog/prio.go index a21218dd1..b5e4ba666 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -85,13 +85,13 @@ func calcStaticPriorities() [][]float32 { noteUsage(0.2, "str") case sys.BufferSockaddr: noteUsage(1.0, "sockaddr") + case sys.BufferFilename: + noteUsage(1.0, "filename") default: panic("unknown buffer kind") } case *sys.VmaType: noteUsage(0.5, "vma") - case *sys.FilenameType: - noteUsage(1.0, "filename") case *sys.IntType: switch a.Kind { case sys.IntPlain: diff --git a/prog/prog.go b/prog/prog.go index 26e7dc0b8..8e8d3018e 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -106,8 +106,6 @@ func (a *Arg) Size() uintptr { case *sys.IntType, *sys.LenType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, *sys.FileoffType, *sys.ResourceType, *sys.VmaType, *sys.PtrType: return typ.Size() - case *sys.FilenameType: - return uintptr(len(a.Data)) case *sys.BufferType: return uintptr(len(a.Data)) case *sys.StructType: diff --git a/prog/rand.go b/prog/rand.go index 99fcd96a5..15db64d4e 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -732,6 +732,9 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) case sys.BufferFilesystem: data := r.filesystem(s) return dataArg(a, data), nil + case sys.BufferFilename: + filename := r.filename(s) + return dataArg(a, []byte(filename)), nil case sys.BufferSockaddr: data := r.sockaddr(s) if a.Dir() == sys.DirOut { @@ -782,9 +785,6 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) v = r.randRangeInt(a.RangeBegin, a.RangeEnd) } return constArg(a, v), nil - case *sys.FilenameType: - filename := r.filename(s) - return dataArg(a, []byte(filename)), nil case *sys.ArrayType: count := uintptr(0) switch a.Kind { diff --git a/prog/validation.go b/prog/validation.go index 1628e38fa..701d0ce3d 100644 --- a/prog/validation.go +++ b/prog/validation.go @@ -76,12 +76,6 @@ func (c *Call) validate(ctx *validCtx) error { default: return fmt.Errorf("syscall %v: fd arg '%v' has bad kind %v", c.Meta.Name, typ.Name(), arg.Kind) } - case *sys.FilenameType: - switch arg.Kind { - case ArgData: - default: - return fmt.Errorf("syscall %v: filename arg '%v' has bad kind %v", c.Meta.Name, typ.Name(), arg.Kind) - } case *sys.StructType, *sys.ArrayType: switch arg.Kind { case ArgGroup: diff --git a/sys/decl.go b/sys/decl.go index 66dc4370a..997298e8a 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -118,6 +118,7 @@ const ( BufferBlobRand BufferKind = iota BufferBlobRange BufferString + BufferFilename BufferSockaddr BufferFilesystem BufferAlgType @@ -251,18 +252,6 @@ func (t *IntType) Align() uintptr { return t.Size() } -type FilenameType struct { - TypeCommon -} - -func (t *FilenameType) Size() uintptr { - panic("filename size is not statically known") -} - -func (t *FilenameType) Align() uintptr { - return 1 -} - type ArrayKind int const ( @@ -513,7 +502,7 @@ func ForeachType(meta *Call, f func(Type)) { } case *ResourceType, *FileoffType, *BufferType, *VmaType, *LenType, *FlagsType, *ConstType, - *StrConstType, *IntType, *FilenameType: + *StrConstType, *IntType: default: panic("unknown type") } diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index c66f2af7a..bf3f57d8f 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -552,7 +552,7 @@ func generateArg( ptrCommonHdr := common() dir = "in" opt = false - fmt.Fprintf(out, "&PtrType{%v, Type: &FilenameType{%v}}", ptrCommonHdr, common()) + fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferFilename}}", ptrCommonHdr, common()) case "array": if len(a) != 1 && len(a) != 2 { failf("wrong number of arguments for %v arg %v, want 1 or 2, got %v", typ, name, len(a)) -- cgit mrf-deployment From f085c198ba2dd95ce46a66ec8f8e6b472c3cca14 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 29 Oct 2016 16:06:40 -0600 Subject: sys: replace FileoffType with IntType{Kind: IntFileoff} FileoffType is effectively an int, no need for a separate type. Also remove fd option from fileoff as it is unused and use story is unclear. --- prog/mutation.go | 2 +- prog/prio.go | 3 +-- prog/prog.go | 4 +--- prog/rand.go | 17 +++++++---------- sys/README.md | 5 ++--- sys/decl.go | 18 ++---------------- sys/sys.txt | 18 +++++++++--------- sysgen/sysgen.go | 8 ++++---- 8 files changed, 27 insertions(+), 48 deletions(-) (limited to 'sys') diff --git a/prog/mutation.go b/prog/mutation.go index 166d5a065..72535f656 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -60,7 +60,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { baseSize = base.Res.Size() } switch a := arg.Type.(type) { - case *sys.IntType, *sys.FlagsType, *sys.FileoffType, *sys.ResourceType, *sys.VmaType: + case *sys.IntType, *sys.FlagsType, *sys.ResourceType, *sys.VmaType: arg1, calls1 := r.generateArg(s, arg.Type) p.replaceArg(c, arg, arg1, calls1) case *sys.BufferType: diff --git a/prog/prio.go b/prog/prio.go index b5e4ba666..9b0ace782 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -94,8 +94,7 @@ func calcStaticPriorities() [][]float32 { noteUsage(0.5, "vma") case *sys.IntType: switch a.Kind { - case sys.IntPlain: - case sys.IntRange: + case sys.IntPlain, sys.IntFileoff, sys.IntRange: case sys.IntSignalno: noteUsage(1.0, "signalno") case sys.IntInaddr: diff --git a/prog/prog.go b/prog/prog.go index 8e8d3018e..4ffc3e6bf 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -95,8 +95,6 @@ func (a *Arg) Value() uintptr { return encodeValue(a.Val, typ.Size(), typ.BigEndian) case *sys.LenType: return encodeValue(a.Val, typ.Size(), typ.BigEndian) - case *sys.FileoffType: - return encodeValue(a.Val, typ.Size(), typ.BigEndian) } return a.Val } @@ -104,7 +102,7 @@ func (a *Arg) Value() uintptr { func (a *Arg) Size() uintptr { switch typ := a.Type.(type) { case *sys.IntType, *sys.LenType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, - *sys.FileoffType, *sys.ResourceType, *sys.VmaType, *sys.PtrType: + *sys.ResourceType, *sys.VmaType, *sys.PtrType: return typ.Size() case *sys.BufferType: return uintptr(len(a.Data)) diff --git a/prog/rand.go b/prog/rand.go index 15db64d4e..6415277eb 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -663,7 +663,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) // output arguments (their elements can be referenced in subsequent calls). switch typ.(type) { case *sys.IntType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, - *sys.FileoffType, *sys.ResourceType, *sys.VmaType: + *sys.ResourceType, *sys.VmaType: return constArg(typ, 0), nil } } @@ -703,15 +703,6 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) }, ) return arg, calls - case *sys.FileoffType: - // TODO: can do better - var arg *Arg - r.choose( - 90, func() { arg = constArg(a, 0) }, - 10, func() { arg = constArg(a, r.rand(100)) }, - 1, func() { arg = constArg(a, r.randInt()) }, - ) - return arg, nil case *sys.BufferType: switch a.Kind { case sys.BufferBlobRand, sys.BufferBlobRange: @@ -781,6 +772,12 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) v = uintptr(r.inaddr(s)) case sys.IntInport: v = uintptr(r.inport(s)) + case sys.IntFileoff: + r.choose( + 90, func() { v = 0 }, + 10, func() { v = r.rand(100) }, + 1, func() { v = r.randInt() }, + ) case sys.IntRange: v = r.randRangeInt(a.RangeBegin, a.RangeEnd) } diff --git a/sys/README.md b/sys/README.md index 18b3c76ab..28b1b712a 100644 --- a/sys/README.md +++ b/sys/README.md @@ -23,7 +23,7 @@ Pseudo-formal grammar of syscall description: type = typename [ "[" type-options "]" ] typename = "const" | "intN" | "intptr" | "flags" | "array" | "ptr" | "buffer" | "string" | "strconst" | "filename" | - "fileoff" | "len" | "bytesize" | "vma" + "len" | "bytesize" | "vma" type-options = [type-opt ["," type-opt]] ``` common type-options include: @@ -48,8 +48,7 @@ rest of the type-options are type-specific: "strconst": a pointer to a constant string, type-options: the underlying string (for example "/dev/dsp") "filename": a file/link/dir name - "fileoff": offset within a file, type-options: - argname of the file + "fileoff": offset within a file "len": length of another field (for array it is number of elements), type-options: argname of the object "bytesize": similar to "len", but always denotes the size in bytes, type-options: diff --git a/sys/decl.go b/sys/decl.go index 997298e8a..d5ec9a547 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -97,21 +97,6 @@ func (t *ResourceType) Align() uintptr { return t.Desc.Type.Align() } -type FileoffType struct { - TypeCommon - TypeSize uintptr - BigEndian bool - File string -} - -func (t *FileoffType) Size() uintptr { - return t.TypeSize -} - -func (t *FileoffType) Align() uintptr { - return t.Size() -} - type BufferKind int const ( @@ -232,6 +217,7 @@ const ( IntSignalno IntInaddr IntInport + IntFileoff // offset within a file IntRange ) @@ -500,7 +486,7 @@ func ForeachType(meta *Call, f func(Type)) { for _, opt := range a.Options { rec(opt) } - case *ResourceType, *FileoffType, *BufferType, + case *ResourceType, *BufferType, *VmaType, *LenType, *FlagsType, *ConstType, *StrConstType, *IntType: default: diff --git a/sys/sys.txt b/sys/sys.txt index be0d10860..8ac03e8dc 100644 --- a/sys/sys.txt +++ b/sys/sys.txt @@ -79,14 +79,14 @@ openat(fd fd_dir, file filename, flags flags[open_flags], mode flags[open_mode]) creat(file filename, mode flags[open_mode]) fd close(fd fd) read(fd fd, buf buffer[out], count len[buf]) len[buf] -pread64(fd fd, buf buffer[out], count len[buf], pos fileoff[fd]) +pread64(fd fd, buf buffer[out], count len[buf], pos fileoff) readv(fd fd, vec ptr[in, array[iovec_out]], vlen len[vec]) -preadv(fd fd, vec ptr[in, array[iovec_out]], vlen len[vec], off fileoff[fd]) +preadv(fd fd, vec ptr[in, array[iovec_out]], vlen len[vec], off fileoff) write(fd fd, buf buffer[in], count len[buf]) len[buf] -pwrite64(fd fd, buf buffer[in], count len[buf], pos fileoff[fd]) +pwrite64(fd fd, buf buffer[in], count len[buf], pos fileoff) writev(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec]) -pwritev(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec], off fileoff[fd]) -lseek(fd fd, offset fileoff[fd], whence flags[seek_whence]) +pwritev(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec], off fileoff) +lseek(fd fd, offset fileoff, whence flags[seek_whence]) dup(oldfd fd) fd dup2(oldfd fd, newfd fd) fd @@ -96,9 +96,9 @@ pipe(pipefd ptr[out, pipefd]) pipe2(pipefd ptr[out, pipefd], flags flags[pipe_flags]) tee(fdin fd, fdout fd, len int64, f flags[splice_flags]) -splice(fdin fd, offin fileoff[fdin], fdout fd, offout fileoff[fdout], len int64, f flags[splice_flags]) +splice(fdin fd, offin fileoff, fdout fd, offout fileoff, len int64, f flags[splice_flags]) vmsplice(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec], f flags[splice_flags]) -sendfile(fdout fd, fdin fd, off ptr[inout, fileoff[fdin, int64], opt], count int64) +sendfile(fdout fd, fdin fd, off ptr[inout, fileoff[int64], opt], count int64) stat(file filename, statbuf ptr[out, stat]) lstat(file filename, statbuf ptr[out, stat]) @@ -136,14 +136,14 @@ ioctl$UFFDIO_WAKE(fd fd_uffd, cmd const[UFFDIO_WAKE], arg ptr[in, uffdio_range]) ioctl$UFFDIO_COPY(fd fd_uffd, cmd const[UFFDIO_WAKE], arg ptr[in, uffdio_range]) ioctl$UFFDIO_ZEROPAGE(fd fd_uffd, cmd const[UFFDIO_WAKE], arg ptr[in, uffdio_range]) -mmap(addr vma, len len[addr], prot flags[mmap_prot], flags flags[mmap_flags], fd fd, offset fileoff[fd]) vma +mmap(addr vma, len len[addr], prot flags[mmap_prot], flags flags[mmap_flags], fd fd, offset fileoff) vma munmap(addr vma, len len[addr]) mremap(addr vma, len len[addr], newlen len[newaddr], flags flags[mremap_flags], newaddr vma) vma remap_file_pages(addr vma, size len[addr], prot flags[mmap_prot], pgoff intptr, flags flags[mmap_flags]) mprotect(addr vma, len len[addr], prot flags[mmap_prot]) msync(addr vma, len len[addr], f flags[msync_flags]) madvise(addr vma, len len[addr], advice flags[madvise_flags]) -fadvise64(fd fd, offset fileoff[fd], len intptr, advice flags[fadvise_flags]) +fadvise64(fd fd, offset fileoff, len intptr, advice flags[fadvise_flags]) readahead(fd fd, off intptr, count intptr) mbind(addr vma, len len[addr], mode flags[mbind_mode], nodemask ptr[in, int64], maxnode intptr, flags flags[mbind_flags]) move_pages(pid pid, nr len[pages], pages ptr[in, array[vma]], nodes ptr[in, array[int32], opt], status ptr[out, array[int32]], flags flags[move_pages_flags]) diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index bf3f57d8f..0ebffb229 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -387,16 +387,16 @@ func generateArg( size := uint64(ptrSize) bigEndian := false if isField { - if want := 2; len(a) != want { + if want := 1; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - size, bigEndian = decodeIntType(a[1]) + size, bigEndian = decodeIntType(a[0]) } else { - if want := 1; len(a) != want { + if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } } - fmt.Fprintf(out, "&FileoffType{%v, File: \"%v\", TypeSize: %v, BigEndian: %v}", common(), a[0], size, bigEndian) + fmt.Fprintf(out, "&IntType{%v, TypeSize: %v, BigEndian: %v, Kind: IntFileoff}", common(), size, bigEndian) case "buffer": canBeArg = true if want := 1; len(a) != want { -- cgit mrf-deployment From 5ed6283b64f91c8aa036122b18974aabed4c5249 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 29 Oct 2016 17:00:35 -0600 Subject: sys: don't imply pointer indirection for string arguments In preparation for extending string functionality and to make it less magical. --- sys/README.md | 2 +- sys/bpf.txt | 2 +- sys/key.txt | 8 ++++---- sys/perf.txt | 2 +- sys/sndcontrol.txt | 2 +- sys/socket.txt | 2 +- sys/sys.txt | 34 +++++++++++++++++----------------- sysgen/sysgen.go | 6 +----- 8 files changed, 27 insertions(+), 31 deletions(-) (limited to 'sys') diff --git a/sys/README.md b/sys/README.md index 28b1b712a..89638aa12 100644 --- a/sys/README.md +++ b/sys/README.md @@ -44,7 +44,7 @@ rest of the type-options are type-specific: type of the object; direction (in/out/inout) "buffer": a pointer to a memory buffer (like read/write buffer argument), type-options: direction (in/out/inout) - "string": a pointer to a memory buffer, similar to buffer[in] + "string": a zero-terminated memory buffer (no pointer indirection implied) "strconst": a pointer to a constant string, type-options: the underlying string (for example "/dev/dsp") "filename": a file/link/dir name diff --git a/sys/bpf.txt b/sys/bpf.txt index 68b4c0ab9..e7338cc53 100644 --- a/sys/bpf.txt +++ b/sys/bpf.txt @@ -52,7 +52,7 @@ bpf_prog { type flags[bpf_prog_type, int32] ninsn len[insns, int32] insns ptr[in, array[bpf_insn]] - license string + license ptr[in, string] loglev int32 logsize len[log, int32] log buffer[out] diff --git a/sys/key.txt b/sys/key.txt index 6c431682c..c0b18f5e8 100644 --- a/sys/key.txt +++ b/sys/key.txt @@ -6,17 +6,17 @@ include resource key[int32]: KEY_SPEC_THREAD_KEYRING, KEY_SPEC_PROCESS_KEYRING, KEY_SPEC_SESSION_KEYRING, KEY_SPEC_USER_KEYRING, KEY_SPEC_USER_SESSION_KEYRING, KEY_SPEC_GROUP_KEYRING, KEY_SPEC_REQKEY_AUTH_KEY, KEY_SPEC_REQUESTOR_KEYRING -add_key(type string, desc string, payload buffer[in, opt], paylen len[payload], keyring flags[keyring_type]) key -request_key(type string, desc string, callout string, keyring flags[keyring_type]) key +add_key(type ptr[in, string], desc ptr[in, string], payload buffer[in, opt], paylen len[payload], keyring flags[keyring_type]) key +request_key(type ptr[in, string], desc ptr[in, string], callout ptr[in, string], keyring flags[keyring_type]) key keyctl$get_keyring_id(code const[KEYCTL_GET_KEYRING_ID], key key, create intptr) -keyctl$join(code const[KEYCTL_JOIN_SESSION_KEYRING], session string) +keyctl$join(code const[KEYCTL_JOIN_SESSION_KEYRING], session ptr[in, string]) keyctl$update(code const[KEYCTL_UPDATE], key key, payload buffer[in, opt], paylen len[payload]) keyctl$revoke(code const[KEYCTL_REVOKE], key key) keyctl$describe(code const[KEYCTL_DESCRIBE], key key, desc buffer[out], len len[desc]) keyctl$clear(code const[KEYCTL_CLEAR], key key) keyctl$link(code const[KEYCTL_LINK], key1 key, key2 key) keyctl$unlink(code const[KEYCTL_UNLINK], key1 key, key2 key) -keyctl$search(code const[KEYCTL_SEARCH], key key, type string, desc string, ring key) +keyctl$search(code const[KEYCTL_SEARCH], key key, type ptr[in, string], desc ptr[in, string], ring key) keyctl$read(code const[KEYCTL_READ], key key, payload buffer[out], len len[payload]) keyctl$chown(code const[KEYCTL_CHOWN], key key, uid uid, gid gid) # perm is a mask of KEY_POS_VIEW, etc consants, but they cover almost whole int32. diff --git a/sys/perf.txt b/sys/perf.txt index a860d75c8..e35ad22b9 100644 --- a/sys/perf.txt +++ b/sys/perf.txt @@ -15,7 +15,7 @@ ioctl$PERF_EVENT_IOC_REFRESH(fd fd_perf, cmd const[PERF_EVENT_IOC_REFRESH], refr ioctl$PERF_EVENT_IOC_PERIOD(fd fd_perf, cmd const[PERF_EVENT_IOC_PERIOD], period ptr[in, int64]) ioctl$PERF_EVENT_IOC_ID(fd fd_perf, cmd const[PERF_EVENT_IOC_ID], id ptr[out, int64]) ioctl$PERF_EVENT_IOC_SET_OUTPUT(fd fd_perf, cmd const[PERF_EVENT_IOC_SET_OUTPUT], other fd_perf) -ioctl$PERF_EVENT_IOC_SET_FILTER(fd fd_perf, cmd const[PERF_EVENT_IOC_SET_FILTER], filter string) +ioctl$PERF_EVENT_IOC_SET_FILTER(fd fd_perf, cmd const[PERF_EVENT_IOC_SET_FILTER], filter ptr[in, string]) ioctl$PERF_EVENT_IOC_SET_BPF(fd fd_perf, cmd const[PERF_EVENT_IOC_SET_BPF], prog fd_bpf_prog) perf_flags = PERF_FLAG_FD_NO_GROUP, PERF_FLAG_FD_OUTPUT, PERF_FLAG_PID_CGROUP, PERF_FLAG_FD_CLOEXEC diff --git a/sys/sndcontrol.txt b/sys/sndcontrol.txt index 20d5cc320..3e3b8a359 100644 --- a/sys/sndcontrol.txt +++ b/sys/sndcontrol.txt @@ -61,7 +61,7 @@ snd_ctl_elem_info { items int32 item int32 name array[int8, 64] - nameptr string + nameptr ptr[in, string] namelen len[nameptr, int32] pad1 array[const[0, int8], 44] d array[int16, 4] diff --git a/sys/socket.txt b/sys/socket.txt index b2db95849..ca4dfeaf6 100644 --- a/sys/socket.txt +++ b/sys/socket.txt @@ -46,7 +46,7 @@ ioctl$SIOCINQ(fd sock, cmd const[SIOCINQ], arg ptr[out, int32]) setsockopt$sock_void(fd sock, level const[SOL_SOCKET], optname flags[sockopt_opt_sock_void], optval const[0], optlen const[0]) getsockopt$sock_int(fd sock, level const[SOL_SOCKET], optname flags[sockopt_opt_sock_int], optval ptr[out, int32], optlen ptr[inout, len[optval, int32]]) setsockopt$sock_int(fd sock, level const[SOL_SOCKET], optname flags[sockopt_opt_sock_int], optval ptr[in, int32], optlen len[optval]) -setsockopt$sock_str(fd sock, level const[SOL_SOCKET], optname const[SO_BINDTODEVICE], optval string, optlen len[optval]) +setsockopt$sock_str(fd sock, level const[SOL_SOCKET], optname const[SO_BINDTODEVICE], optval ptr[in, string], optlen len[optval]) getsockopt$sock_linger(fd sock, level const[SOL_SOCKET], optname const[SO_LINGER], optval ptr[out, linger], optlen ptr[inout, len[optval, int32]]) setsockopt$sock_linger(fd sock, level const[SOL_SOCKET], optname const[SO_LINGER], optval ptr[in, linger], optlen len[optval]) getsockopt$sock_cred(fd sock, level const[SOL_SOCKET], optname const[SO_PEERCRED], optval ptr[out, ucred], optlen ptr[inout, len[optval, int32]]) diff --git a/sys/sys.txt b/sys/sys.txt index 8ac03e8dc..13d2d2830 100644 --- a/sys/sys.txt +++ b/sys/sys.txt @@ -156,7 +156,7 @@ mlock2(addr vma, size len[addr], flags flags[mlock_flags]) munlock(addr vma, size len[addr]) mlockall(flags flags[mlockall_flags]) munlockall() -memfd_create(name string, flags flags[memfd_flags]) fd +memfd_create(name ptr[in, string], flags flags[memfd_flags]) fd unshare(flags flags[clone_flags]) kcmp(pid1 pid, pid2 pid, type flags[kcmp_flags], fd1 fd, fd2 fd) @@ -220,7 +220,7 @@ prctl$intptr(option flags[prctl_code_intptr], arg intptr) prctl$getreaper(option flags[prctl_code_getreaper], arg ptr[out, intptr]) prctl$setendian(option const[PR_SET_ENDIAN], arg flags[prctl_endian]) prctl$setfpexc(option const[PR_SET_FPEXC], arg flags[prctl_fpexc]) -prctl$setname(option const[PR_SET_NAME], name string) +prctl$setname(option const[PR_SET_NAME], name ptr[in, string]) prctl$getname(option const[PR_GET_NAME], name buffer[out]) prctl$setptracer(option const[PR_SET_PTRACER], pid pid) prctl$seccomp(option const[PR_SET_SECCOMP], mode flags[prctl_seccomp_mode], prog ptr[in, sock_fprog]) @@ -230,12 +230,12 @@ arch_prctl(code flags[arch_prctl_code], addr buffer[in]) seccomp(op flags[seccomp_op], flags flags[seccomp_flags], prog ptr[in, sock_fprog]) resource fd_mq[fd] -mq_open(name string, flags flags[mq_open_flags], mode flags[open_mode], attr ptr[in, mq_attr]) fd_mq +mq_open(name ptr[in, string], flags flags[mq_open_flags], mode flags[open_mode], attr ptr[in, mq_attr]) fd_mq mq_timedsend(mqd fd_mq, msg buffer[in], msglen len[msg], prio intptr, timeout ptr[in, timespec, opt]) mq_timedreceive(mqd fd_mq, msg buffer[out], msglen len[msg], prio intptr, timeout ptr[in, timespec, opt]) mq_notify(mqd fd_mq, notif ptr[in, sigevent]) mq_getsetattr(mqd fd_mq, attr ptr[in, mq_attr], oldattr ptr[out, mq_attr, opt]) -mq_unlink(name string) +mq_unlink(name ptr[in, string]) resource ipc[int32]: 0, 0xffffffffffffffff resource ipc_msq[ipc] @@ -350,16 +350,16 @@ mount$fs(src filesystem, dst filename, type filesystem, flags flags[mount_flags] umount2(path filename, flags flags[umount_flags]) pivot_root(new_root filename, put_old filename) -sysfs$1(option flags[sysfs_opt1], fsname string) +sysfs$1(option flags[sysfs_opt1], fsname ptr[in, string]) sysfs$2(option flags[sysfs_opt2], fsindex intptr, fsname buffer[out]) sysfs$3(option flags[sysfs_opt3]) statfs(path filename, buf buffer[out]) fstatfs(fd fd, buf buffer[out]) uselib(lib filename) -init_module(mod string, len len[mod], args string) -finit_module(fd fd, args string, flags flags[finit_module_flags]) -delete_module(name string, flags flags[delete_module_flags]) +init_module(mod ptr[in, string], len len[mod], args ptr[in, string]) +finit_module(fd fd, args ptr[in, string], flags flags[finit_module_flags]) +delete_module(name ptr[in, string], flags flags[delete_module_flags]) kexec_load(entry intptr, nr_segments len[segments], segments ptr[in, array[kexec_segment]], flags flags[kexec_load_flags]) get_kernel_syms(table buffer[out]) syslog(cmd flags[syslog_cmd], buf buffer[out, opt], len len[buf]) @@ -381,18 +381,18 @@ ioprio_set$pid(which flags[ioprio_which_pid], who pid, prio intptr) ioprio_set$uid(which flags[ioprio_which_uid], who uid, prio intptr) setns(fd fd, type flags[ns_type]) -setxattr(path filename, name string, val string, size len[val], flags flags[setxattr_flags]) -lsetxattr(path filename, name string, val string, size len[val], flags flags[setxattr_flags]) -fsetxattr(fd fd, name string, val string, size len[val], flags flags[setxattr_flags]) -getxattr(path filename, name string, val buffer[out], size len[val]) -lgetxattr(path filename, name string, val buffer[out], size len[val]) -fgetxattr(fd fd, name string, val buffer[out], size len[val]) +setxattr(path filename, name ptr[in, string], val ptr[in, string], size len[val], flags flags[setxattr_flags]) +lsetxattr(path filename, name ptr[in, string], val ptr[in, string], size len[val], flags flags[setxattr_flags]) +fsetxattr(fd fd, name ptr[in, string], val ptr[in, string], size len[val], flags flags[setxattr_flags]) +getxattr(path filename, name ptr[in, string], val buffer[out], size len[val]) +lgetxattr(path filename, name ptr[in, string], val buffer[out], size len[val]) +fgetxattr(fd fd, name ptr[in, string], val buffer[out], size len[val]) listxattr(path filename, list buffer[out], size len[list]) llistxattr(path filename, list buffer[out], size len[list]) flistxattr(fd fd, list buffer[out], size len[list]) -removexattr(path filename, name string) -lremovexattr(path filename, name string) -fremovexattr(fd fd, name string) +removexattr(path filename, name ptr[in, string]) +lremovexattr(path filename, name ptr[in, string]) +fremovexattr(fd fd, name ptr[in, string]) resource timerid[int32] timer_create(id flags[clock_id], ev ptr[in, sigevent], timerid ptr[out, timerid]) diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index 0ebffb229..7159ef70c 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -407,14 +407,10 @@ func generateArg( opt = false fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferBlobRand}}", ptrCommonHdr, common()) case "string": - canBeArg = true if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) } - ptrCommonHdr := common() - dir = "in" - opt = false - fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferString}}", ptrCommonHdr, common()) + fmt.Fprintf(out, "&BufferType{%v, Kind: BufferString}", common()) case "filesystem": canBeArg = true if want := 0; len(a) != want { -- cgit mrf-deployment From 588a542b2a23ba477031bf20b4c46b0f40a04b7d Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 31 Oct 2016 15:15:13 -0600 Subject: sys: add string flags Allow to define string flags in txt descriptions. E.g.: filesystem = "ext2", "ext3", "ext4" and then use it in string type: ptr[in, string[filesystem]] --- host/host.go | 30 ++++++++------ prog/mutation.go | 12 +++--- prog/prio.go | 2 +- prog/prog.go | 2 +- prog/rand.go | 28 +++---------- sys/README.md | 10 +++-- sys/decl.go | 30 +++++--------- sys/dri.txt | 6 +-- sys/input.txt | 6 +-- sys/kdbus.txt | 2 +- sys/kvm.txt | 4 +- sys/random.txt | 4 +- sys/sndcontrol.txt | 2 +- sys/sndseq.txt | 2 +- sys/sndtimer.txt | 2 +- sys/sys.txt | 113 ++++++++++++++++++++++++++-------------------------- sys/tlk_device.txt | 2 +- sys/tty.txt | 2 +- sys/tun.txt | 2 +- sysgen/sysgen.go | 39 +++++++++--------- sysparser/lexer.go | 23 +++++++++-- sysparser/parser.go | 3 +- 22 files changed, 161 insertions(+), 165 deletions(-) (limited to 'sys') diff --git a/host/host.go b/host/host.go index 49cf78e57..a58964e8c 100644 --- a/host/host.go +++ b/host/host.go @@ -60,11 +60,7 @@ func isSupportedSyzkall(c *sys.Call) bool { case "syz_test": return false case "syz_open_dev": - ptr, ok := c.Args[0].(*sys.PtrType) - if !ok { - return true - } - fname, ok := ptr.Type.(*sys.StrConstType) + fname, ok := extractStringConst(c.Args[0]) if !ok { panic("first open arg is not a pointer to string const") } @@ -84,7 +80,7 @@ func isSupportedSyzkall(c *sys.Call) bool { } return false } - return check(fname.Val[:len(fname.Val)-1]) + return check(fname) case "syz_open_pts": return true case "syz_fuse_mount": @@ -112,17 +108,27 @@ func isSupportedSocket(c *sys.Call) bool { } func isSupportedOpen(c *sys.Call) bool { - ptr, ok := c.Args[0].(*sys.PtrType) - if !ok { - panic("first open arg is not a pointer") - } - fname, ok := ptr.Type.(*sys.StrConstType) + fname, ok := extractStringConst(c.Args[0]) if !ok { return true } - fd, err := syscall.Open(fname.Val[:len(fname.Val)-1], syscall.O_RDONLY, 0) + fd, err := syscall.Open(fname, syscall.O_RDONLY, 0) if fd != -1 { syscall.Close(fd) } return err == nil } + +func extractStringConst(typ sys.Type) (string, bool) { + ptr, ok := typ.(*sys.PtrType) + if !ok { + panic("first open arg is not a pointer to string const") + } + str, ok := ptr.Type.(*sys.BufferType) + if !ok || str.Kind != sys.BufferString || len(str.Values) != 1 { + return "", false + } + v := str.Values[0] + v = v[:len(v)-1] // string terminating \x00 + return v, true +} diff --git a/prog/mutation.go b/prog/mutation.go index 72535f656..e861725c8 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -89,10 +89,8 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { if r.bin() { arg.Data = mutateData(r, append([]byte{}, arg.Data...), int(0), ^int(0)) } else { - arg.Data = r.randString(s) + arg.Data = r.randString(s, a.Values) } - case sys.BufferFilesystem: - arg.Data = r.filesystem(s) case sys.BufferFilename: arg.Data = []byte(r.filename(s)) case sys.BufferSockaddr: @@ -170,7 +168,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { p.replaceArg(c, arg, arg1, calls) case *sys.LenType: panic("bad arg returned by mutationArgs: LenType") - case *sys.ConstType, *sys.StrConstType: + case *sys.ConstType: panic("bad arg returned by mutationArgs: ConstType") default: panic(fmt.Sprintf("bad arg returned by mutationArgs: %#v, type=%#v", *arg, arg.Type)) @@ -322,9 +320,13 @@ func mutationArgs(c *Call) (args, bases []*Arg) { case *sys.LenType: // Size is updated when the size-of arg change. return - case *sys.ConstType, *sys.StrConstType: + case *sys.ConstType: // Well, this is const. return + case *sys.BufferType: + if typ.Kind == sys.BufferString && len(typ.Values) == 1 { + return // string const + } } if arg.Type.Dir() == sys.DirOut { return diff --git a/prog/prio.go b/prog/prio.go index 9b0ace782..a6919372d 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -80,7 +80,7 @@ func calcStaticPriorities() [][]float32 { } case *sys.BufferType: switch a.Kind { - case sys.BufferBlobRand, sys.BufferBlobRange, sys.BufferFilesystem, sys.BufferAlgType, sys.BufferAlgName: + case sys.BufferBlobRand, sys.BufferBlobRange, sys.BufferAlgType, sys.BufferAlgName: case sys.BufferString: noteUsage(0.2, "str") case sys.BufferSockaddr: diff --git a/prog/prog.go b/prog/prog.go index 4ffc3e6bf..e3a0febd2 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -101,7 +101,7 @@ func (a *Arg) Value() uintptr { func (a *Arg) Size() uintptr { switch typ := a.Type.(type) { - case *sys.IntType, *sys.LenType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, + case *sys.IntType, *sys.LenType, *sys.FlagsType, *sys.ConstType, *sys.ResourceType, *sys.VmaType, *sys.PtrType: return typ.Size() case *sys.BufferType: diff --git a/prog/rand.go b/prog/rand.go index 6415277eb..30d0ba4aa 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -258,7 +258,10 @@ func (r *randGen) sockaddr(s *state) []byte { return data } -func (r *randGen) randString(s *state) []byte { +func (r *randGen) randString(s *state, vals []string) []byte { + if len(vals) != 0 { + return []byte(vals[r.Intn(len(vals))]) + } if len(s.strings) != 0 && r.bin() { // Return an existing string. strings := make([]string, 0, len(s.strings)) @@ -288,20 +291,6 @@ func (r *randGen) randString(s *state) []byte { return buf.Bytes() } -func (r *randGen) filesystem(s *state) []byte { - dict := []string{"sysfs", "rootfs", "ramfs", "tmpfs", "devtmpfs", "debugfs", - "securityfs", "sockfs", "pipefs", "anon_inodefs", "devpts", "ext3", "ext2", "ext4", - "hugetlbfs", "vfat", "ecryptfs", "kdbusfs", "fuseblk", "fuse", "rpc_pipefs", - "nfs", "nfs4", "nfsd", "binfmt_misc", "autofs", "xfs", "jfs", "msdos", "ntfs", - "minix", "hfs", "hfsplus", "qnx4", "ufs", "btrfs", "configfs", "ncpfs", "qnx6", - "exofs", "befs", "vxfs", "gfs2", "gfs2meta", "fusectl", "bfs", "nsfs", "efs", - "cifs", "efivarfs", "affs", "tracefs", "bdev", "ocfs2", "ocfs2_dlmfs", "hpfs", - "proc", "afs", "reiserfs", "jffs2", "romfs", "aio", "sysv", "v7", "udf", - "ceph", "pstore", "adfs", "9p", "hostfs", "squashfs", "cramfs", "iso9660", - "coda", "nilfs2", "logfs", "overlay", "f2fs", "omfs", "ubifs", "openpromfs"} - return []byte(dict[r.Intn(len(dict))] + "\x00") -} - func (r *randGen) algType(s *state) []byte { dict := []string{"aead", "hash", "rng", "skcipher"} res := make([]byte, 14) @@ -662,7 +651,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) // in subsequent calls. For the same reason we do generate pointer/array/struct // output arguments (their elements can be referenced in subsequent calls). switch typ.(type) { - case *sys.IntType, *sys.FlagsType, *sys.ConstType, *sys.StrConstType, + case *sys.IntType, *sys.FlagsType, *sys.ConstType, *sys.ResourceType, *sys.VmaType: return constArg(typ, 0), nil } @@ -718,10 +707,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) } return dataArg(a, data), nil case sys.BufferString: - data := r.randString(s) - return dataArg(a, data), nil - case sys.BufferFilesystem: - data := r.filesystem(s) + data := r.randString(s, a.Values) return dataArg(a, data), nil case sys.BufferFilename: filename := r.filename(s) @@ -761,8 +747,6 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) return constArg(a, r.flags(a.Vals)), nil case *sys.ConstType: return constArg(a, a.Val), nil - case *sys.StrConstType: - return dataArg(a, []byte(a.Val)), nil case *sys.IntType: v := r.randInt() switch a.Kind { diff --git a/sys/README.md b/sys/README.md index 89638aa12..161c1e73e 100644 --- a/sys/README.md +++ b/sys/README.md @@ -44,9 +44,9 @@ rest of the type-options are type-specific: type of the object; direction (in/out/inout) "buffer": a pointer to a memory buffer (like read/write buffer argument), type-options: direction (in/out/inout) - "string": a zero-terminated memory buffer (no pointer indirection implied) - "strconst": a pointer to a constant string, type-options: - the underlying string (for example "/dev/dsp") + "string": a zero-terminated memory buffer (no pointer indirection implied), type-options: + either a string value in quotes for constant strings (e.g. "foo"), + or a reference to string flags "filename": a file/link/dir name "fileoff": offset within a file "len": length of another field (for array it is number of elements), type-options: @@ -61,6 +61,10 @@ Flags are described as: ``` flagname = const ["," const]* ``` +or for string flags as: +``` + flagname = "\"" literal "\"" ["," "\"" literal "\""]* +``` ### Structs diff --git a/sys/decl.go b/sys/decl.go index d5ec9a547..2f86ea87c 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -105,7 +105,6 @@ const ( BufferString BufferFilename BufferSockaddr - BufferFilesystem BufferAlgType BufferAlgName ) @@ -115,6 +114,8 @@ type BufferType struct { Kind BufferKind RangeBegin uintptr // for BufferBlobRange kind RangeEnd uintptr // for BufferBlobRange kind + SubKind string + Values []string // possible values for BufferString kind } func (t *BufferType) Size() uintptr { @@ -123,14 +124,16 @@ func (t *BufferType) Size() uintptr { return 14 case BufferAlgName: return 64 + case BufferString: + if len(t.Values) == 1 { + return uintptr(len(t.Values[0])) + } case BufferBlobRange: if t.RangeBegin == t.RangeEnd { return t.RangeBegin } - fallthrough - default: - panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name())) } + panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name())) } func (t *BufferType) Align() uintptr { @@ -196,20 +199,6 @@ func (t *ConstType) Align() uintptr { return t.Size() } -type StrConstType struct { - TypeCommon - TypeSize uintptr - Val string -} - -func (t *StrConstType) Size() uintptr { - return uintptr(len(t.Val)) -} - -func (t *StrConstType) Align() uintptr { - return 1 -} - type IntKind int const ( @@ -486,9 +475,8 @@ func ForeachType(meta *Call, f func(Type)) { for _, opt := range a.Options { rec(opt) } - case *ResourceType, *BufferType, - *VmaType, *LenType, *FlagsType, *ConstType, - *StrConstType, *IntType: + case *ResourceType, *BufferType, *VmaType, *LenType, + *FlagsType, *ConstType, *IntType: default: panic("unknown type") } diff --git a/sys/dri.txt b/sys/dri.txt index 3c5753f23..bc35016e4 100644 --- a/sys/dri.txt +++ b/sys/dri.txt @@ -10,9 +10,9 @@ resource drm_agp_handle[intptr] resource drm_gem_handle[int32] resource drm_gem_name[int32] -syz_open_dev$dri(dev strconst["/dev/dri/card#"], id intptr, flags flags[open_flags]) fd_dri -syz_open_dev$dricontrol(dev strconst["/dev/dri/controlD#"], id intptr, flags flags[open_flags]) fd_dri -syz_open_dev$drirender(dev strconst["/dev/dri/renderD#"], id intptr, flags flags[open_flags]) fd_dri +syz_open_dev$dri(dev ptr[in, string["/dev/dri/card#"]], id intptr, flags flags[open_flags]) fd_dri +syz_open_dev$dricontrol(dev ptr[in, string["/dev/dri/controlD#"]], id intptr, flags flags[open_flags]) fd_dri +syz_open_dev$drirender(dev ptr[in, string["/dev/dri/renderD#"]], id intptr, flags flags[open_flags]) fd_dri ioctl$DRM_IOCTL_VERSION(fd fd_dri, cmd const[DRM_IOCTL_VERSION], arg ptr[in, drm_version]) ioctl$DRM_IOCTL_GET_UNIQUE(fd fd_dri, cmd const[DRM_IOCTL_GET_UNIQUE], arg ptr[in, drm_unique_out]) diff --git a/sys/input.txt b/sys/input.txt index 236d6c89c..4266c2b2b 100644 --- a/sys/input.txt +++ b/sys/input.txt @@ -6,10 +6,10 @@ include resource fd_evdev[fd] # There seems to be nothing special we can do with this fd. -syz_open_dev$mouse(dev strconst["/dev/input/mouse#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$mice(dev strconst["/dev/input/mice"], id const[0], flags flags[open_flags]) fd +syz_open_dev$mouse(dev ptr[in, string["/dev/input/mouse#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$mice(dev ptr[in, string["/dev/input/mice"]], id const[0], flags flags[open_flags]) fd -syz_open_dev$evdev(dev strconst["/dev/input/event#"], id intptr, flags flags[open_flags]) fd_evdev +syz_open_dev$evdev(dev ptr[in, string["/dev/input/event#"]], id intptr, flags flags[open_flags]) fd_evdev write$evdev(fd fd_evdev, data ptr[in, array[input_event]], len bytesize[data]) diff --git a/sys/kdbus.txt b/sys/kdbus.txt index 5d40b8625..97bd49e70 100644 --- a/sys/kdbus.txt +++ b/sys/kdbus.txt @@ -6,7 +6,7 @@ include resource fd_kdbus[fd] -openat$kdbus(fd const[AT_FDCWD], file strconst["/dev/kdbus"], flags flags[open_flags], mode const[0]) fd_kdbus +openat$kdbus(fd const[AT_FDCWD], file ptr[in, string["/dev/kdbus"]], flags flags[open_flags], mode const[0]) fd_kdbus ioctl$kdbus_bus_make(fd fd_kdbus, cmd const[KDBUS_CMD_BUS_MAKE], arg ptr[in, kdbus_cmd_bus_make]) ioctl$kdbus_ep_make(fd fd_kdbus, cmd const[KDBUS_CMD_ENDPOINT_MAKE], arg ptr[in, kdbus_cmd_ep_make]) ioctl$kdbus_ep_update(fd fd_kdbus, cmd const[KDBUS_CMD_ENDPOINT_UPDATE], arg ptr[in, kdbus_cmd_ep_update]) diff --git a/sys/kvm.txt b/sys/kvm.txt index b80f4ce72..96e73d74e 100644 --- a/sys/kvm.txt +++ b/sys/kvm.txt @@ -9,7 +9,7 @@ resource fd_kvm[fd] resource fd_kvmvm[fd] resource fd_kvmcpu[fd] -syz_open_dev$kvm(dev strconst["/dev/kvm"], id const[0], flags flags[open_flags]) fd_kvm +syz_open_dev$kvm(dev ptr[in, string["/dev/kvm"]], id const[0], flags flags[open_flags]) fd_kvm ioctl$KVM_CREATE_VM(fd fd_kvm, cmd const[KVM_CREATE_VM], type const[0]) fd_kvmvm ioctl$KVM_GET_MSR_INDEX_LIST(fd fd_kvm, cmd const[KVM_GET_MSR_INDEX_LIST], arg ptr[in, kvm_msr_list]) @@ -99,7 +99,7 @@ ioctl$KVM_SET_GUEST_DEBUG(fd fd_kvmcpu, cmd const[KVM_SET_GUEST_DEBUG], arg ptr[ ioctl$KVM_SMI(fd fd_kvmcpu, cmd const[KVM_SMI]) # TODO: extend support (there are some ioctls) -openat$xenevtchn(fd const[AT_FDCWD], file strconst["/dev/xen/evtchn"], flags flags[open_flags], mode const[0]) fd +openat$xenevtchn(fd const[AT_FDCWD], file ptr[in, string["/dev/xen/evtchn"]], flags flags[open_flags], mode const[0]) fd kvm_mem_region_flags = KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_READONLY, KVM_MEMSLOT_INVALID, KVM_MEMSLOT_INCOHERENT kvm_mp_state = KVM_MP_STATE_RUNNABLE, KVM_MP_STATE_UNINITIALIZED, KVM_MP_STATE_INIT_RECEIVED, KVM_MP_STATE_HALTED, KVM_MP_STATE_SIPI_RECEIVED, KVM_MP_STATE_STOPPED, KVM_MP_STATE_CHECK_STOP, KVM_MP_STATE_OPERATING, KVM_MP_STATE_LOAD diff --git a/sys/random.txt b/sys/random.txt index 7c8fd11c0..234d1be40 100755 --- a/sys/random.txt +++ b/sys/random.txt @@ -5,8 +5,8 @@ include resource fd_random[fd] -syz_open_dev$random(dev strconst["/dev/random"], id const[0], flags flags[open_flags]) fd_random -syz_open_dev$urandom(dev strconst["/dev/urandom"], id const[0], flags flags[open_flags]) fd_random +syz_open_dev$random(dev ptr[in, string["/dev/random"]], id const[0], flags flags[open_flags]) fd_random +syz_open_dev$urandom(dev ptr[in, string["/dev/urandom"]], id const[0], flags flags[open_flags]) fd_random ioctl$RNDGETENTCNT(fd fd_random, cmd const[RNDGETENTCNT], arg ptr[out, int32]) ioctl$RNDADDTOENTCNT(fd fd_random, cmd const[RNDADDTOENTCNT], arg ptr[in, int32]) diff --git a/sys/sndcontrol.txt b/sys/sndcontrol.txt index 3e3b8a359..1ec602f03 100644 --- a/sys/sndcontrol.txt +++ b/sys/sndcontrol.txt @@ -5,7 +5,7 @@ include resource fd_sndctrl[fd] -syz_open_dev$sndctrl(dev strconst["/dev/snd/controlC#"], id intptr, flags flags[open_flags]) fd_sndctrl +syz_open_dev$sndctrl(dev ptr[in, string["/dev/snd/controlC#"]], id intptr, flags flags[open_flags]) fd_sndctrl ioctl$SNDRV_CTL_IOCTL_PVERSION(fd fd_sndctrl, cmd const[SNDRV_CTL_IOCTL_PVERSION], arg buffer[out]) ioctl$SNDRV_CTL_IOCTL_CARD_INFO(fd fd_sndctrl, cmd const[SNDRV_CTL_IOCTL_CARD_INFO], arg buffer[out]) diff --git a/sys/sndseq.txt b/sys/sndseq.txt index 62a844ed7..40ad7118d 100644 --- a/sys/sndseq.txt +++ b/sys/sndseq.txt @@ -6,7 +6,7 @@ include resource fd_sndseq[fd] -syz_open_dev$sndseq(dev strconst["/dev/snd/seq"], id const[0], flags flags[open_flags]) fd_sndseq +syz_open_dev$sndseq(dev ptr[in, string["/dev/snd/seq"]], id const[0], flags flags[open_flags]) fd_sndseq write$sndseq(fd fd_sndseq, data ptr[in, array[snd_seq_event]], len bytesize[data]) ioctl$SNDRV_SEQ_IOCTL_PVERSION(fd fd_sndseq, cmd const[SNDRV_SEQ_IOCTL_PVERSION], arg ptr[out, int32]) diff --git a/sys/sndtimer.txt b/sys/sndtimer.txt index 67e0a13a8..f7eebc2af 100644 --- a/sys/sndtimer.txt +++ b/sys/sndtimer.txt @@ -5,7 +5,7 @@ include resource fd_sndtimer[fd] -syz_open_dev$sndtimer(dev strconst["/dev/snd/timer"], id const[0], flags flags[open_flags]) fd_sndtimer +syz_open_dev$sndtimer(dev ptr[in, string["/dev/snd/timer"]], id const[0], flags flags[open_flags]) fd_sndtimer ioctl$SNDRV_TIMER_IOCTL_PVERSION(fd fd_sndtimer, cmd const[SNDRV_TIMER_IOCTL_PVERSION], arg ptr[out, int32]) ioctl$SNDRV_TIMER_IOCTL_NEXT_DEVICE(fd fd_sndtimer, cmd const[SNDRV_TIMER_IOCTL_NEXT_DEVICE], arg ptr[in, snd_timer_id]) diff --git a/sys/sys.txt b/sys/sys.txt index 13d2d2830..c6da9a800 100644 --- a/sys/sys.txt +++ b/sys/sys.txt @@ -345,14 +345,16 @@ getdents64(fd fd_dir, ent buffer[out], count len[ent]) name_to_handle_at(fd fd_dir, file filename, handle ptr[in, file_handle], mnt ptr[out, int32], flags flags[name_to_handle_at_flags]) open_by_handle_at(mountdirfd fd, handle ptr[in, file_handle], flags flags[open_flags]) -mount(src filename, dst filename, type filesystem, flags flags[mount_flags], data buffer[in]) -mount$fs(src filesystem, dst filename, type filesystem, flags flags[mount_flags], data buffer[in]) +mount(src filename, dst filename, type ptr[in, string[filesystem]], flags flags[mount_flags], data buffer[in]) +mount$fs(src ptr[in, string[filesystem]], dst filename, type ptr[in, string[filesystem]], flags flags[mount_flags], data buffer[in]) umount2(path filename, flags flags[umount_flags]) pivot_root(new_root filename, put_old filename) -sysfs$1(option flags[sysfs_opt1], fsname ptr[in, string]) -sysfs$2(option flags[sysfs_opt2], fsindex intptr, fsname buffer[out]) -sysfs$3(option flags[sysfs_opt3]) +filesystem = "sysfs", "rootfs", "ramfs", "tmpfs", "devtmpfs", "debugfs", "securityfs", "sockfs", "pipefs", "anon_inodefs", "devpts", "ext3", "ext2", "ext4", "hugetlbfs", "vfat", "ecryptfs", "kdbusfs", "fuseblk", "fuse", "rpc_pipefs", "nfs", "nfs4", "nfsd", "binfmt_misc", "autofs", "xfs", "jfs", "msdos", "ntfs", "minix", "hfs", "hfsplus", "qnx4", "ufs", "btrfs", "configfs", "ncpfs", "qnx6", "exofs", "befs", "vxfs", "gfs2", "gfs2meta", "fusectl", "bfs", "nsfs", "efs", "cifs", "efivarfs", "affs", "tracefs", "bdev", "ocfs2", "ocfs2_dlmfs", "hpfs", "proc", "afs", "reiserfs", "jffs2", "romfs", "aio", "sysv", "v7", "udf", "ceph", "pstore", "adfs", "9p", "hostfs", "squashfs", "cramfs", "iso9660", "coda", "nilfs2", "logfs", "overlay", "f2fs", "omfs", "ubifs", "openpromfs" + +sysfs$1(option const[1], fsname ptr[in, string]) +sysfs$2(option const[2], fsindex intptr, fsname buffer[out]) +sysfs$3(option const[3]) statfs(path filename, buf buffer[out]) fstatfs(fd fd, buf buffer[out]) @@ -463,55 +465,55 @@ membarrier(cmd const[1], flags const[0]) # These devices are relatively safe (don't reboot and don't corrupt kernel memory). # They need a more comprehensive support. But let at least open them for now, # maybe fuzzer will be able to skrew them in a useful way. -syz_open_dev$floppy(dev strconst["/dev/fd#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$pktcdvd(dev strconst["/dev/pktcdvd/control"], id const[0], flags flags[open_flags]) fd -syz_open_dev$lightnvm(dev strconst["/dev/lightnvm/control"], id const[0], flags flags[open_flags]) fd -syz_open_dev$vcs(dev strconst["/dev/vcs"], id const[0], flags flags[open_flags]) fd -syz_open_dev$vcsn(dev strconst["/dev/vcs#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$vcsa(dev strconst["/dev/vcsa#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$vga_arbiter(dev strconst["/dev/vga_arbiter"], id const[0], flags flags[open_flags]) fd -syz_open_dev$vhci(dev strconst["/dev/vhci"], id const[0], flags flags[open_flags]) fd -syz_open_dev$userio(dev strconst["/dev/userio"], id const[0], flags flags[open_flags]) fd -syz_open_dev$rtc(dev strconst["/dev/rtc"], id const[0], flags flags[open_flags]) fd -syz_open_dev$rfkill(dev strconst["/dev/rfkill"], id const[0], flags flags[open_flags]) fd -syz_open_dev$qat_adf_ctl(dev strconst["/dev/qat_adf_ctl"], id const[0], flags flags[open_flags]) fd -syz_open_dev$ppp(dev strconst["/dev/ppp"], id const[0], flags flags[open_flags]) fd -syz_open_dev$mixer(dev strconst["/dev/mixer"], id const[0], flags flags[open_flags]) fd -syz_open_dev$irnet(dev strconst["/dev/irnet"], id const[0], flags flags[open_flags]) fd -syz_open_dev$hwrng(dev strconst["/dev/hwrng"], id const[0], flags flags[open_flags]) fd -syz_open_dev$hpet(dev strconst["/dev/hpet"], id const[0], flags flags[open_flags]) fd -syz_open_dev$hidraw0(dev strconst["/dev/hidraw0"], id const[0], flags flags[open_flags]) fd -syz_open_dev$fb0(dev strconst["/dev/fb0"], id const[0], flags flags[open_flags]) fd -syz_open_dev$cuse(dev strconst["/dev/cuse"], id const[0], flags flags[open_flags]) fd -syz_open_dev$console(dev strconst["/dev/console"], id const[0], flags flags[open_flags]) fd -syz_open_dev$capi20(dev strconst["/dev/capi20"], id const[0], flags flags[open_flags]) fd -syz_open_dev$autofs(dev strconst["/dev/autofs"], id const[0], flags flags[open_flags]) fd -syz_open_dev$binder(dev strconst["/dev/binder"], id const[0], flags flags[open_flags]) fd -syz_open_dev$ion(dev strconst["/dev/ion"], id const[0], flags flags[open_flags]) fd -syz_open_dev$keychord(dev strconst["/dev/keychord"], id const[0], flags flags[open_flags]) fd -syz_open_dev$zygote(dev strconst["/dev/socket/zygote"], id const[0], flags flags[open_flags]) fd -syz_open_dev$sw_sync(dev strconst["/dev/sw_sync"], id const[0], flags flags[open_flags]) fd -syz_open_dev$sr(dev strconst["/dev/sr0"], id const[0], flags flags[open_flags]) fd -syz_open_dev$sequencer(dev strconst["/dev/sequencer"], id const[0], flags flags[open_flags]) fd -syz_open_dev$sequencer2(dev strconst["/dev/sequencer2"], id const[0], flags flags[open_flags]) fd -syz_open_dev$dsp(dev strconst["/dev/dsp"], id const[0], flags flags[open_flags]) fd -syz_open_dev$audio(dev strconst["/dev/audio"], id const[0], flags flags[open_flags]) fd -syz_open_dev$usbmon(dev strconst["/dev/usbmon#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$sg(dev strconst["/dev/sg#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$midi(dev strconst["/dev/midi#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$loop(dev strconst["/dev/loop#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$ircomm(dev strconst["/dev/ircomm#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$dspn(dev strconst["/dev/dsp#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$dmmidi(dev strconst["/dev/dmmidi#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$admmidi(dev strconst["/dev/admmidi#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$adsp(dev strconst["/dev/adsp#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$amidi(dev strconst["/dev/amidi#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$audion(dev strconst["/dev/audio#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$usb(dev strconst["/dev/bus/usb/00#/00#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$sndhw(dev strconst["/dev/snd/hwC#D#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$sndmidi(dev strconst["/dev/snd/midiC#D#"], id intptr, flags flags[open_flags]) fd -syz_open_dev$sndpcmc(dev strconst["/dev/snd/pcmC#D#c"], id intptr, flags flags[open_flags]) fd -syz_open_dev$sndpcmp(dev strconst["/dev/snd/pcmC#D#p"], id intptr, flags flags[open_flags]) fd +syz_open_dev$floppy(dev ptr[in, string["/dev/fd#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$pktcdvd(dev ptr[in, string["/dev/pktcdvd/control"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$lightnvm(dev ptr[in, string["/dev/lightnvm/control"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$vcs(dev ptr[in, string["/dev/vcs"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$vcsn(dev ptr[in, string["/dev/vcs#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$vcsa(dev ptr[in, string["/dev/vcsa#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$vga_arbiter(dev ptr[in, string["/dev/vga_arbiter"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$vhci(dev ptr[in, string["/dev/vhci"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$userio(dev ptr[in, string["/dev/userio"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$rtc(dev ptr[in, string["/dev/rtc"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$rfkill(dev ptr[in, string["/dev/rfkill"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$qat_adf_ctl(dev ptr[in, string["/dev/qat_adf_ctl"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$ppp(dev ptr[in, string["/dev/ppp"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$mixer(dev ptr[in, string["/dev/mixer"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$irnet(dev ptr[in, string["/dev/irnet"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$hwrng(dev ptr[in, string["/dev/hwrng"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$hpet(dev ptr[in, string["/dev/hpet"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$hidraw0(dev ptr[in, string["/dev/hidraw0"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$fb0(dev ptr[in, string["/dev/fb0"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$cuse(dev ptr[in, string["/dev/cuse"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$console(dev ptr[in, string["/dev/console"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$capi20(dev ptr[in, string["/dev/capi20"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$autofs(dev ptr[in, string["/dev/autofs"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$binder(dev ptr[in, string["/dev/binder"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$ion(dev ptr[in, string["/dev/ion"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$keychord(dev ptr[in, string["/dev/keychord"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$zygote(dev ptr[in, string["/dev/socket/zygote"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$sw_sync(dev ptr[in, string["/dev/sw_sync"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$sr(dev ptr[in, string["/dev/sr0"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$sequencer(dev ptr[in, string["/dev/sequencer"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$sequencer2(dev ptr[in, string["/dev/sequencer2"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$dsp(dev ptr[in, string["/dev/dsp"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$audio(dev ptr[in, string["/dev/audio"]], id const[0], flags flags[open_flags]) fd +syz_open_dev$usbmon(dev ptr[in, string["/dev/usbmon#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$sg(dev ptr[in, string["/dev/sg#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$midi(dev ptr[in, string["/dev/midi#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$loop(dev ptr[in, string["/dev/loop#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$ircomm(dev ptr[in, string["/dev/ircomm#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$dspn(dev ptr[in, string["/dev/dsp#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$dmmidi(dev ptr[in, string["/dev/dmmidi#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$admmidi(dev ptr[in, string["/dev/admmidi#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$adsp(dev ptr[in, string["/dev/adsp#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$amidi(dev ptr[in, string["/dev/amidi#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$audion(dev ptr[in, string["/dev/audio#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$usb(dev ptr[in, string["/dev/bus/usb/00#/00#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$sndhw(dev ptr[in, string["/dev/snd/hwC#D#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$sndmidi(dev ptr[in, string["/dev/snd/midiC#D#"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$sndpcmc(dev ptr[in, string["/dev/snd/pcmC#D#c"]], id intptr, flags flags[open_flags]) fd +syz_open_dev$sndpcmp(dev ptr[in, string["/dev/snd/pcmC#D#p"]], id intptr, flags flags[open_flags]) fd @@ -1167,9 +1169,6 @@ ioprio_which_uid = IOPRIO_WHO_USER setxattr_flags = XATTR_CREATE, XATTR_REPLACE ns_type = 0, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWUTS personality_flags = PER_LINUX, PER_SVR4, PER_SVR3, PER_OSR5, PER_WYSEV386, PER_ISCR4, PER_BSD, PER_XENIX, PER_LINUX32, PER_IRIX32, PER_IRIXN32, PER_IRIX64, PER_RISCOS, PER_SOLARIS, PER_UW7, PER_OSF4, PER_HPUX, ADDR_NO_RANDOMIZE, MMAP_PAGE_ZERO, ADDR_COMPAT_LAYOUT, READ_IMPLIES_EXEC, ADDR_LIMIT_32BIT, SHORT_INODE, WHOLE_SECONDS, STICKY_TIMEOUTS, ADDR_LIMIT_3GB -sysfs_opt1 = 1 -sysfs_opt2 = 2 -sysfs_opt3 = 3 clock_id = CLOCK_REALTIME, CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_RAW, CLOCK_BOOTTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID sigprocmask_how = SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK getitimer_which = ITIMER_REAL, ITIMER_VIRTUAL, ITIMER_PROF diff --git a/sys/tlk_device.txt b/sys/tlk_device.txt index 7535d16f7..1d5bd8229 100644 --- a/sys/tlk_device.txt +++ b/sys/tlk_device.txt @@ -12,7 +12,7 @@ include resource fd_tlk[fd] resource te_session_id[int32] -syz_open_dev$tlk_device(dev strconst["/dev/tlk_device"], id const[0], flags flags[open_flags]) fd_tlk +syz_open_dev$tlk_device(dev ptr[in, string["/dev/tlk_device"]], id const[0], flags flags[open_flags]) fd_tlk ioctl$TE_IOCTL_OPEN_CLIENT_SESSION(fd fd_tlk, cmd const[TE_IOCTL_OPEN_CLIENT_SESSION], arg ptr[inout, te_opensession]) ioctl$TE_IOCTL_CLOSE_CLIENT_SESSION(fd fd_tlk, cmd const[TE_IOCTL_CLOSE_CLIENT_SESSION], arg ptr[inout, te_closesession]) diff --git a/sys/tty.txt b/sys/tty.txt index 67b11b754..e9717806c 100644 --- a/sys/tty.txt +++ b/sys/tty.txt @@ -8,7 +8,7 @@ include resource fd_tty[fd] -openat$ptmx(fd const[AT_FDCWD], file strconst["/dev/ptmx"], flags flags[open_flags], mode const[0]) fd_tty +openat$ptmx(fd const[AT_FDCWD], file ptr[in, string["/dev/ptmx"]], flags flags[open_flags], mode const[0]) fd_tty syz_open_pts(fd fd_tty, flags flags[open_flags]) fd_tty ioctl$TCGETS(fd fd_tty, cmd const[TCGETS], arg ptr[out, termios]) ioctl$TCSETS(fd fd_tty, cmd const[TCSETS], arg ptr[in, termios]) diff --git a/sys/tun.txt b/sys/tun.txt index 04e640786..a730ed86a 100755 --- a/sys/tun.txt +++ b/sys/tun.txt @@ -6,7 +6,7 @@ include resource fd_tun[fd] -syz_open_dev$tun(dev strconst["/dev/net/tun"], id const[0], flags flags[open_flags]) fd_tun +syz_open_dev$tun(dev ptr[in, string["/dev/net/tun"]], id const[0], flags flags[open_flags]) fd_tun write$tun(fd fd_tun, buf ptr[in, tun_buffer], count len[buf]) ioctl$TUNGETFEATURES(fd fd_tun, cmd const[TUNGETFEATURES], arg ptr[out, int32]) diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index 7159ef70c..6913b9c81 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -407,19 +407,27 @@ func generateArg( opt = false fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferBlobRand}}", ptrCommonHdr, common()) case "string": - if want := 0; len(a) != want { - failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + if len(a) != 0 && len(a) != 1 { + failf("wrong number of arguments for %v arg %v, want 0 or 1, got %v", typ, name, len(a)) } - fmt.Fprintf(out, "&BufferType{%v, Kind: BufferString}", common()) - case "filesystem": - canBeArg = true - if want := 0; len(a) != want { - failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + var vals []string + subkind := "" + if len(a) == 1 { + if a[0][0] == '"' { + vals = append(vals, a[0][1:len(a[0])-1]) + } else { + ok := false + vals, ok = desc.StrFlags[a[0]] + if !ok { + failf("unknown string flags %v", a[0]) + } + subkind = a[0] + } + for i, s := range vals { + vals[i] = s + "\x00" + } } - ptrCommonHdr := common() - dir = "in" - opt = false - fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferFilesystem}}", ptrCommonHdr, common()) + fmt.Fprintf(out, "&BufferType{%v, Kind: BufferString, SubKind: %q, Values: %#v}", common(), subkind, vals) case "sockaddr": if want := 0; len(a) != want { failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) @@ -503,15 +511,6 @@ func generateArg( skipSyscall(fmt.Sprintf("missing const %v", a[0])) } fmt.Fprintf(out, "&ConstType{%v, TypeSize: %v, BigEndian: %v, Val: uintptr(%v)}", common(), size, bigEndian, val) - case "strconst": - canBeArg = true - if want := 1; len(a) != want { - failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) - } - ptrCommonHdr := common() - dir = "in" - opt = false - fmt.Fprintf(out, "&PtrType{%v, Type: &StrConstType{%v, Val: \"%v\"}}", ptrCommonHdr, common(), a[0]+"\\x00") case "int8", "int16", "int32", "int64", "intptr", "int16be", "int32be", "int64be", "intptrbe": canBeArg = true size, bigEndian := decodeIntType(typ) diff --git a/sysparser/lexer.go b/sysparser/lexer.go index 18143c901..a3b8f58ed 100644 --- a/sysparser/lexer.go +++ b/sysparser/lexer.go @@ -18,6 +18,7 @@ type Description struct { Structs map[string]Struct Unnamed map[string][]string Flags map[string][]string + StrFlags map[string][]string Resources map[string]Resource } @@ -51,6 +52,7 @@ func Parse(in io.Reader) *Description { structs := make(map[string]Struct) unnamed := make(map[string][]string) flags := make(map[string][]string) + strflags := make(map[string][]string) resources := make(map[string]Resource) var str *Struct for p.Scan() { @@ -192,12 +194,24 @@ func Parse(in io.Reader) *Description { case '=': // flag p.Parse('=') - vals := []string{p.Ident()} - for !p.EOF() { + str := p.Char() == '"' + var vals []string + for { + v := p.Ident() + if str { + v = v[1 : len(v)-1] + } + vals = append(vals, v) + if p.EOF() { + break + } p.Parse(',') - vals = append(vals, p.Ident()) } - flags[name] = vals + if str { + strflags[name] = vals + } else { + flags[name] = vals + } case '{', '[': p.Parse(ch) if _, ok := structs[name]; ok { @@ -224,6 +238,7 @@ func Parse(in io.Reader) *Description { Structs: structs, Unnamed: unnamed, Flags: flags, + StrFlags: strflags, Resources: resources, } } diff --git a/sysparser/parser.go b/sysparser/parser.go index 590847b0e..d5021eee6 100644 --- a/sysparser/parser.go +++ b/sysparser/parser.go @@ -70,11 +70,10 @@ func (p *parser) Ident() string { start, end := p.i, 0 if p.Char() == '"' { p.Parse('"') - start++ for p.Char() != '"' { p.i++ } - end = p.i + end = p.i + 1 p.Parse('"') } else { for p.i < len(p.s) && -- cgit mrf-deployment From 3a65453870b12f5c42739c27d99df8fc58358f88 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 7 Nov 2016 14:45:15 -0800 Subject: sys: allow to specify buffer size for strings This allows to write: string[salg_type, 14] which will give a string buffer of size 14 regardless of actual string size. Convert salg_type/salg_name to this. --- prog/mutation.go | 6 +----- prog/prio.go | 6 ++++-- prog/rand.go | 58 ++++++++++++-------------------------------------------- sys/README.md | 3 ++- sys/decl.go | 18 ++++++++++-------- sys/socket.txt | 7 +++++-- sysgen/sysgen.go | 33 ++++++++++++++++++++++++++------ 7 files changed, 61 insertions(+), 70 deletions(-) (limited to 'sys') diff --git a/prog/mutation.go b/prog/mutation.go index e861725c8..8d5fa36a4 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -89,16 +89,12 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { if r.bin() { arg.Data = mutateData(r, append([]byte{}, arg.Data...), int(0), ^int(0)) } else { - arg.Data = r.randString(s, a.Values) + arg.Data = r.randString(s, a.Values, a.Dir()) } case sys.BufferFilename: arg.Data = []byte(r.filename(s)) case sys.BufferSockaddr: arg.Data = r.sockaddr(s) - case sys.BufferAlgType: - arg.Data = r.algType(s) - case sys.BufferAlgName: - arg.Data = r.algName(s) default: panic("unknown buffer kind") } diff --git a/prog/prio.go b/prog/prio.go index a6919372d..59a205a5d 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -80,9 +80,11 @@ func calcStaticPriorities() [][]float32 { } case *sys.BufferType: switch a.Kind { - case sys.BufferBlobRand, sys.BufferBlobRange, sys.BufferAlgType, sys.BufferAlgName: + case sys.BufferBlobRand, sys.BufferBlobRange: case sys.BufferString: - noteUsage(0.2, "str") + if a.SubKind != "" { + noteUsage(0.2, fmt.Sprintf("str-%v", a.SubKind)) + } case sys.BufferSockaddr: noteUsage(1.0, "sockaddr") case sys.BufferFilename: diff --git a/prog/rand.go b/prog/rand.go index 30d0ba4aa..eb24dcc4d 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -258,7 +258,17 @@ func (r *randGen) sockaddr(s *state) []byte { return data } -func (r *randGen) randString(s *state, vals []string) []byte { +func (r *randGen) randString(s *state, vals []string, dir sys.Dir) []byte { + data := r.randStringImpl(s, vals) + if dir == sys.DirOut { + for i := range data { + data[i] = 0 + } + } + return data +} + +func (r *randGen) randStringImpl(s *state, vals []string) []byte { if len(vals) != 0 { return []byte(vals[r.Intn(len(vals))]) } @@ -291,34 +301,6 @@ func (r *randGen) randString(s *state, vals []string) []byte { return buf.Bytes() } -func (r *randGen) algType(s *state) []byte { - dict := []string{"aead", "hash", "rng", "skcipher"} - res := make([]byte, 14) - copy(res, dict[r.Intn(len(dict))]) - return res -} - -func (r *randGen) algName(s *state) []byte { - dict := []string{"cmac(aes)", "ecb(aes)", "cbc(aes)", "hmac(sha1)", "pcbc(fcrypt)", "ghash", - "jitterentropy_rng", "stdrng", "stdrng", "stdrng", "stdrng", "hmac(sha256)", "stdrng", - "stdrng", "stdrng", "stdrng", "stdrng", "842", "lz4hc", "lz4", "lzo", "crct10dif", "crc32", - "crc32c", "michael_mic", "zlib", "deflate", "poly1305", "chacha20", "salsa20", "seed", - "anubis", "khazad", "xeta", "xtea", "tea", "ecb(arc4)", "arc4", "cast6", "cast5", "camellia", - "aes", "tnepres", "serpent", "twofish", "blowfish", "fcrypt", "des3_ede", "des", "tgr128", - "tgr160", "tgr192", "wp256", "wp384", "wp512", "sha384", "sha512", "sha224", "sha256", - "sha1", "rmd320", "rmd256", "rmd160", "rmd128", "md5", "md4", "digest_null", "compress_null", - "ecb(cipher_null)", "cipher_null", "rsa", "poly1305", "xts(serpent)", "lrw(serpent)", - "ctr(serpent)", "cbc(serpent)", "__ecb-serpent-sse2", "ecb(serpent)", "__xts-serpent-sse2", - "__lrw-serpent-sse2", "__ctr-serpent-sse2", "__cbc-serpent-sse2", "__ecb-serpent-sse2", - "salsa20", "xts(twofish)", "lrw(twofish)", "ctr(twofish)", "cbc(twofish)", "ecb(twofish)", - "twofish", "ctr(blowfish)", "cbc(blowfish)", "ecb(blowfish)", "blowfish", "xts(camellia)", - "lrw(camellia)", "ctr(camellia)", "cbc(camellia)", "ecb(camellia)", "camellia", "ctr(des3_ede)", - "cbc(des3_ede)", "ecb(des3_ede)", "des3_ede", "aes"} - res := make([]byte, 64) - copy(res, dict[r.Intn(len(dict))]) - return res -} - func isSpecialStruct(typ sys.Type) func(r *randGen, s *state) (*Arg, []*Call) { a, ok := typ.(*sys.StructType) if !ok { @@ -707,7 +689,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) } return dataArg(a, data), nil case sys.BufferString: - data := r.randString(s, a.Values) + data := r.randString(s, a.Values, a.Dir()) return dataArg(a, data), nil case sys.BufferFilename: filename := r.filename(s) @@ -720,22 +702,6 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call) } } return dataArg(a, data), nil - case sys.BufferAlgType: - data := r.algType(s) - if a.Dir() == sys.DirOut { - for i := range data { - data[i] = 0 - } - } - return dataArg(a, data), nil - case sys.BufferAlgName: - data := r.algName(s) - if a.Dir() == sys.DirOut { - for i := range data { - data[i] = 0 - } - } - return dataArg(a, data), nil default: panic("unknown buffer kind") } diff --git a/sys/README.md b/sys/README.md index 161c1e73e..8125a7b7c 100644 --- a/sys/README.md +++ b/sys/README.md @@ -46,7 +46,8 @@ rest of the type-options are type-specific: direction (in/out/inout) "string": a zero-terminated memory buffer (no pointer indirection implied), type-options: either a string value in quotes for constant strings (e.g. "foo"), - or a reference to string flags + or a reference to string flags, + optionally followed by a buffer size (string values will be padded with \x00 to that size) "filename": a file/link/dir name "fileoff": offset within a file "len": length of another field (for array it is number of elements), type-options: diff --git a/sys/decl.go b/sys/decl.go index 2f86ea87c..84c2f8c08 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -105,8 +105,6 @@ const ( BufferString BufferFilename BufferSockaddr - BufferAlgType - BufferAlgName ) type BufferType struct { @@ -120,13 +118,17 @@ type BufferType struct { func (t *BufferType) Size() uintptr { switch t.Kind { - case BufferAlgType: - return 14 - case BufferAlgName: - return 64 case BufferString: - if len(t.Values) == 1 { - return uintptr(len(t.Values[0])) + size := 0 + for _, s := range t.Values { + if size != 0 && size != len(s) { + size = 0 + break + } + size = len(s) + } + if size != 0 { + return uintptr(size) } case BufferBlobRange: if t.RangeBegin == t.RangeEnd { diff --git a/sys/socket.txt b/sys/socket.txt index ca4dfeaf6..74728194f 100644 --- a/sys/socket.txt +++ b/sys/socket.txt @@ -273,10 +273,10 @@ sendmmsg$alg(fd sock_algconn, mmsg ptr[in, array[msghdr_alg]], vlen len[mmsg], f sockaddr_alg { family const[AF_ALG, int16] - type salg_type + type string[salg_type, 14] feat flags[af_alg_type, int32] mask flags[af_alg_type, int32] - name salg_name + name string[salg_name, 64] } msghdr_alg { @@ -320,6 +320,9 @@ cmsghdr_alg_assoc { af_alg_type = CRYPTO_ALG_TYPE_MASK, CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_COMPRESS, CRYPTO_ALG_TYPE_AEAD, CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_ABLKCIPHER, CRYPTO_ALG_TYPE_GIVCIPHER, CRYPTO_ALG_TYPE_DIGEST, CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_SHASH, CRYPTO_ALG_TYPE_AHASH, CRYPTO_ALG_TYPE_RNG, CRYPTO_ALG_TYPE_AKCIPHER, CRYPTO_ALG_TYPE_PCOMPRESS, CRYPTO_ALG_LARVAL, CRYPTO_ALG_DEAD, CRYPTO_ALG_DYING, CRYPTO_ALG_ASYNC, CRYPTO_ALG_NEED_FALLBACK, CRYPTO_ALG_GENIV, CRYPTO_ALG_TESTED, CRYPTO_ALG_INSTANCE, CRYPTO_ALG_KERN_DRIVER_ONLY, CRYPTO_ALG_INTERNAL +salg_type = "aead", "hash", "rng", "skcipher" +salg_name = "cmac(aes)", "ecb(aes)", "cbc(aes)", "hmac(sha1)", "pcbc(fcrypt)", "ghash", "jitterentropy_rng", "stdrng", "stdrng", "stdrng", "stdrng", "hmac(sha256)", "stdrng", "stdrng", "stdrng", "stdrng", "stdrng", "842", "lz4hc", "lz4", "lzo", "crct10dif", "crc32", "crc32c", "michael_mic", "zlib", "deflate", "poly1305", "chacha20", "salsa20", "seed", "anubis", "khazad", "xeta", "xtea", "tea", "ecb(arc4)", "arc4", "cast6", "cast5", "camellia", "aes", "tnepres", "serpent", "twofish", "blowfish", "fcrypt", "des3_ede", "des", "tgr128", "tgr160", "tgr192", "wp256", "wp384", "wp512", "sha384", "sha512", "sha224", "sha256", "sha1", "rmd320", "rmd256", "rmd160", "rmd128", "md5", "md4", "digest_null", "compress_null", "ecb(cipher_null)", "cipher_null", "rsa", "poly1305", "xts(serpent)", "lrw(serpent)", "ctr(serpent)", "cbc(serpent)", "__ecb-serpent-sse2", "ecb(serpent)", "__xts-serpent-sse2", "__lrw-serpent-sse2", "__ctr-serpent-sse2", "__cbc-serpent-sse2", "__ecb-serpent-sse2", "salsa20", "xts(twofish)", "lrw(twofish)", "ctr(twofish)", "cbc(twofish)", "ecb(twofish)", "twofish", "ctr(blowfish)", "cbc(blowfish)", "ecb(blowfish)", "blowfish", "xts(camellia)", "lrw(camellia)", "ctr(camellia)", "cbc(camellia)", "ecb(camellia)", "camellia", "ctr(des3_ede)", "cbc(des3_ede)", "ecb(des3_ede)", "des3_ede", "aes" + diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index 6913b9c81..fda931b14 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -407,24 +407,45 @@ func generateArg( opt = false fmt.Fprintf(out, "&PtrType{%v, Type: &BufferType{%v, Kind: BufferBlobRand}}", ptrCommonHdr, common()) case "string": - if len(a) != 0 && len(a) != 1 { - failf("wrong number of arguments for %v arg %v, want 0 or 1, got %v", typ, name, len(a)) + if len(a) != 0 && len(a) != 1 && len(a) != 2 { + failf("wrong number of arguments for %v arg %v, want 0-2, got %v", typ, name, len(a)) } var vals []string subkind := "" - if len(a) == 1 { + if len(a) >= 1 { if a[0][0] == '"' { vals = append(vals, a[0][1:len(a[0])-1]) } else { - ok := false - vals, ok = desc.StrFlags[a[0]] + vals1, ok := desc.StrFlags[a[0]] if !ok { failf("unknown string flags %v", a[0]) } + vals = append([]string{}, vals1...) subkind = a[0] } + } + for i, s := range vals { + vals[i] = s + "\x00" + } + if len(a) >= 2 { + var size uint64 + if v, ok := consts[a[1]]; ok { + size = v + } else { + v, err := strconv.ParseUint(a[1], 10, 64) + if err != nil { + failf("failed to parse string length for %v", name, a[1]) + } + size = v + } for i, s := range vals { - vals[i] = s + "\x00" + if uint64(len(s)) > size { + failf("string value %q exceeds buffer length %v for arg %v", s, size, name) + } + for uint64(len(s)) < size { + s += "\x00" + } + vals[i] = s } } fmt.Fprintf(out, "&BufferType{%v, Kind: BufferString, SubKind: %q, Values: %#v}", common(), subkind, vals) -- cgit mrf-deployment