aboutsummaryrefslogtreecommitdiffstats
path: root/prog/encoding.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-03-05 12:07:51 +0100
committerDmitry Vyukov <dvyukov@google.com>2018-03-05 12:10:27 +0100
commitbd5df8f49be704519466f7165c3e8fef85b3f566 (patch)
treea31d6d330d62987ca8e67a1fcfb88656f4201db3 /prog/encoding.go
parentf027f1a3f7c45bafd7f99776548ef73ba3cc22ec (diff)
prog: handle excessive args and fields during program parsing
Tolerate excessive args and fields during program parsing. This is useful after description changes to not lose corpus.
Diffstat (limited to 'prog/encoding.go')
-rw-r--r--prog/encoding.go52
1 files changed, 46 insertions, 6 deletions
diff --git a/prog/encoding.go b/prog/encoding.go
index c8d0fc3e3..890924f3e 100644
--- a/prog/encoding.go
+++ b/prog/encoding.go
@@ -180,7 +180,8 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) {
p.Parse('(')
for i := 0; p.Char() != ')'; i++ {
if i >= len(meta.Args) {
- return nil, fmt.Errorf("wrong call arg count: %v, want %v", i+1, len(meta.Args))
+ eatExcessive(p)
+ break
}
typ := meta.Args[i]
if IsPad(typ) {
@@ -199,10 +200,8 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) {
if !p.EOF() {
return nil, fmt.Errorf("tailing data (line #%v)", p.l)
}
- if len(c.Args) < len(meta.Args) {
- for i := len(c.Args); i < len(meta.Args); i++ {
- c.Args = append(c.Args, target.defaultArg(meta.Args[i]))
- }
+ for i := len(c.Args); i < len(meta.Args); i++ {
+ c.Args = append(c.Args, target.defaultArg(meta.Args[i]))
}
if len(c.Args) != len(meta.Args) {
return nil, fmt.Errorf("wrong call arg count: %v, want %v", len(c.Args), len(meta.Args))
@@ -372,7 +371,8 @@ func (target *Target) parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, e
var inner []Arg
for i := 0; p.Char() != '}'; i++ {
if i >= len(t1.Fields) {
- return nil, fmt.Errorf("wrong struct arg count: %v, want %v", i+1, len(t1.Fields))
+ eatExcessive(p)
+ break
}
fld := t1.Fields[i]
if IsPad(fld) {
@@ -463,6 +463,46 @@ func (target *Target) parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, e
return arg, nil
}
+// Eats excessive call arguments and struct fields to recover after description changes.
+func eatExcessive(p *parser) {
+ paren, brack, brace := 0, 0, 0
+ for !p.EOF() {
+ ch := p.Char()
+ switch ch {
+ case '(':
+ paren++
+ case ')':
+ if paren == 0 {
+ return
+ }
+ paren--
+ case '[':
+ brack++
+ case ']':
+ if brack == 0 {
+ return
+ }
+ brack--
+ case '{':
+ brace++
+ case '}':
+ if brace == 0 {
+ return
+ }
+ brace--
+ case '\'', '"':
+ p.Parse(ch)
+ for !p.EOF() && p.Char() != ch {
+ p.Parse(p.Char())
+ }
+ if p.EOF() {
+ return
+ }
+ }
+ p.Parse(ch)
+ }
+}
+
const (
encodingAddrBase = 0x7f0000000000
maxLineLen = 256 << 10