diff options
-rw-r--r-- | internal/compile/compile.go | 3 | ||||
-rw-r--r-- | resolve/resolve.go | 13 |
2 files changed, 15 insertions, 1 deletions
diff --git a/internal/compile/compile.go b/internal/compile/compile.go index c184e64..300d196 100644 --- a/internal/compile/compile.go +++ b/internal/compile/compile.go @@ -1599,7 +1599,8 @@ func (fcomp *fcomp) args(call *syntax.CallExpr) (op Opcode, arg uint32) { // TODO(adonovan): avoid this with a more flexible encoding. if p >= 256 || n >= 256 { - log.Fatalf("%s: compiler error: too many arguments in call", call.Lparen) + // resolve already checked this; should be unreachable + panic("too many arguments in call") } return CALL + Opcode(callmode), uint32(p<<8 | n) diff --git a/resolve/resolve.go b/resolve/resolve.go index 59c486a..9e21ee1 100644 --- a/resolve/resolve.go +++ b/resolve/resolve.go @@ -670,6 +670,7 @@ func (r *resolver) expr(e syntax.Expr) { r.expr(e.Fn) var seenVarargs, seenKwargs bool var seenName map[string]bool + var n, p int for _, arg := range e.Args { pos, _ := arg.Span() if unop, ok := arg.(*syntax.UnaryExpr); ok && unop.Op == syntax.STARSTAR { @@ -690,6 +691,7 @@ func (r *resolver) expr(e syntax.Expr) { r.expr(arg) } else if binop, ok := arg.(*syntax.BinaryExpr); ok && binop.Op == syntax.EQ { // k=v + n++ if seenKwargs { r.errorf(pos, "argument may not follow **kwargs") } @@ -705,6 +707,7 @@ func (r *resolver) expr(e syntax.Expr) { r.expr(binop.Y) } else { // positional argument + p++ if seenVarargs { r.errorf(pos, "argument may not follow *args") } else if seenKwargs { @@ -716,6 +719,16 @@ func (r *resolver) expr(e syntax.Expr) { } } + // Fail gracefully if compiler-imposed limit is exceeded. + if p >= 256 { + pos, _ := e.Span() + r.errorf(pos, "%v positional arguments in call, limit is 255", p) + } + if n >= 256 { + pos, _ := e.Span() + r.errorf(pos, "%v keyword arguments in call, limit is 255", n) + } + case *syntax.LambdaExpr: if !AllowLambda { r.errorf(e.Lambda, doesnt+"support lambda") |