diff options
Diffstat (limited to 'prog/encoding.go')
| -rw-r--r-- | prog/encoding.go | 84 |
1 files changed, 52 insertions, 32 deletions
diff --git a/prog/encoding.go b/prog/encoding.go index 6e3203984..9ba9a6bb4 100644 --- a/prog/encoding.go +++ b/prog/encoding.go @@ -179,25 +179,51 @@ func (a *ResultArg) serialize(ctx *serializer) { } } -func (target *Target) Deserialize(data []byte) (prog *Prog, err error) { - prog = &Prog{ - Target: target, +type DeserializeMode int + +const ( + Strict DeserializeMode = iota + NonStrict DeserializeMode = iota +) + +func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, error) { + p := newParser(target, data, mode == Strict) + prog, err := p.parseProg() + if err != nil { + return nil, err + } + if err := p.Err(); err != nil { + return nil, err + } + // This validation is done even in non-debug mode because deserialization + // procedure does not catch all bugs (e.g. mismatched types). + // And we can receive bad programs from corpus and hub. + if err := prog.validate(); err != nil { + return nil, err + } + for _, c := range prog.Calls { + target.SanitizeCall(c) + } + return prog, nil +} + +func (p *parser) parseProg() (*Prog, error) { + prog := &Prog{ + Target: p.target, } - p := newParser(target, data) - comment := "" for p.Scan() { if p.EOF() { - if comment != "" { - prog.Comments = append(prog.Comments, comment) - comment = "" + if p.comment != "" { + prog.Comments = append(prog.Comments, p.comment) + p.comment = "" } continue } if p.Char() == '#' { - if comment != "" { - prog.Comments = append(prog.Comments, comment) + if p.comment != "" { + prog.Comments = append(prog.Comments, p.comment) } - comment = strings.TrimSpace(p.s[p.i+1:]) + p.comment = strings.TrimSpace(p.s[p.i+1:]) continue } name := p.Ident() @@ -208,19 +234,22 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) { name = p.Ident() } - meta := target.SyscallMap[name] + meta := p.target.SyscallMap[name] if meta == nil { return nil, fmt.Errorf("unknown syscall %v", name) } c := &Call{ Meta: meta, Ret: MakeReturnArg(meta.Ret), - Comment: comment, + Comment: p.comment, } prog.Calls = append(prog.Calls, c) p.Parse('(') for i := 0; p.Char() != ')'; i++ { if i >= len(meta.Args) { + if p.strict { + return nil, fmt.Errorf("excessive syscall arguments (line #%v)", p.l) + } p.eatExcessive(false) break } @@ -257,24 +286,12 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) { if r != "" && c.Ret != nil { p.vars[r] = c.Ret } - comment = "" + p.comment = "" } - if comment != "" { - prog.Comments = append(prog.Comments, comment) + if p.comment != "" { + prog.Comments = append(prog.Comments, p.comment) } - if err := p.Err(); err != nil { - return nil, err - } - // This validation is done even in non-debug mode because deserialization - // procedure does not catch all bugs (e.g. mismatched types). - // And we can receive bad programs from corpus and hub. - if err := prog.validate(); err != nil { - return nil, err - } - for _, c := range prog.Calls { - target.SanitizeCall(c) - } - return + return prog, nil } func (p *parser) parseArg(typ Type) (Arg, error) { @@ -775,8 +792,10 @@ func (p *parser) deserializeData() ([]byte, error) { } type parser struct { - target *Target - vars map[string]*ResultArg + target *Target + strict bool + vars map[string]*ResultArg + comment string r *bufio.Scanner s string @@ -785,9 +804,10 @@ type parser struct { e error } -func newParser(target *Target, data []byte) *parser { +func newParser(target *Target, data []byte, strict bool) *parser { p := &parser{ target: target, + strict: strict, vars: make(map[string]*ResultArg), r: bufio.NewScanner(bytes.NewReader(data)), } |
