From 07bd1c1ff1a17ae959ddac1c6a34d8598f50151c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20=C3=8D=C3=B1igo?= Date: Fri, 6 Jul 2018 13:01:57 +0200 Subject: [PATCH] Go: Fix panic on call to function with wrong number of arguments --- go/src/core/core.go | 91 +++++++++++++++++++++++++++++++++ go/src/step2_eval/step2_eval.go | 19 +++++++ go/src/step3_env/step3_env.go | 19 +++++++ go/tests/step2_eval.mal | 34 ++++++++++++ go/tests/step3_env.mal | 34 ++++++++++++ go/tests/step4_if_fn_do.mal | 34 ++++++++++++ go/tests/step5_tco.mal | 35 +++++++++++++ go/tests/step6_file.mal | 34 ++++++++++++ go/tests/step7_quote.mal | 34 ++++++++++++ go/tests/step8_macros.mal | 34 ++++++++++++ go/tests/step9_try.mal | 34 ++++++++++++ go/tests/stepA_mal.mal | 34 ++++++++++++ 12 files changed, 436 insertions(+) create mode 100644 go/tests/step2_eval.mal create mode 100644 go/tests/step3_env.mal create mode 100644 go/tests/step4_if_fn_do.mal create mode 100644 go/tests/step6_file.mal create mode 100644 go/tests/step7_quote.mal create mode 100644 go/tests/step8_macros.mal create mode 100644 go/tests/step9_try.mal create mode 100644 go/tests/stepA_mal.mal diff --git a/go/src/core/core.go b/go/src/core/core.go index abbaae89..615f0c46 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -446,28 +446,52 @@ func swap_BANG(a []MalType) (MalType, error) { // core namespace var NS = map[string]MalType{ "=": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return Equal_Q(a[0], a[1]), nil }, "throw": throw, "nil?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Nil_Q(a[0]), nil }, "true?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return True_Q(a[0]), nil }, "false?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return False_Q(a[0]), nil }, "symbol": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Symbol{a[0].(string)}, nil }, "symbol?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Symbol_Q(a[0]), nil }, "string?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return (String_Q(a[0]) && !Keyword_Q(a[0])), nil }, "keyword": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } if Keyword_Q(a[0]) { return a[0], nil } else { @@ -475,13 +499,22 @@ var NS = map[string]MalType{ } }, "keyword?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Keyword_Q(a[0]), nil }, "number?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Number_Q(a[0]), nil }, "fn?": fn_q, "macro?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return MalFunc_Q(a[0]) && a[0].(MalFunc).GetMacro(), nil }, @@ -490,35 +523,65 @@ var NS = map[string]MalType{ "prn": func(a []MalType) (MalType, error) { return prn(a) }, "println": func(a []MalType) (MalType, error) { return println(a) }, "read-string": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return reader.Read_str(a[0].(string)) }, "slurp": slurp, "readline": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return readline.Readline(a[0].(string)) }, "<": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) < a[1].(int), nil }, "<=": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) <= a[1].(int), nil }, ">": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) > a[1].(int), nil }, ">=": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) >= a[1].(int), nil }, "+": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) + a[1].(int), nil }, "-": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) - a[1].(int), nil }, "*": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) * a[1].(int), nil }, "/": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) / a[1].(int), nil }, "time-ms": time_ms, @@ -527,30 +590,45 @@ var NS = map[string]MalType{ return List{a, nil}, nil }, "list?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return List_Q(a[0]), nil }, "vector": func(a []MalType) (MalType, error) { return Vector{a, nil}, nil }, "vector?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Vector_Q(a[0]), nil }, "hash-map": func(a []MalType) (MalType, error) { return NewHashMap(List{a, nil}) }, "map?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return HashMap_Q(a[0]), nil }, "assoc": assoc, "dissoc": dissoc, "get": get, "contains?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return contains_Q(a[0], a[1]) }, "keys": keys, "vals": vals, "sequential?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Sequential_Q(a[0]), nil }, "cons": cons, @@ -568,12 +646,25 @@ var NS = map[string]MalType{ "with-meta": with_meta, "meta": meta, "atom": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return &Atom{a[0], nil}, nil }, "atom?": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 1); e != nil { + return nil, e + } return Atom_Q(a[0]), nil }, "deref": deref, "reset!": reset_BANG, "swap!": swap_BANG, } + +func assertArgNum(a []MalType, n int) error { + if len(a) != n { + return errors.New("wrong number of arguments") + } + return nil +} diff --git a/go/src/step2_eval/step2_eval.go b/go/src/step2_eval/step2_eval.go index 95176956..6eb67b76 100644 --- a/go/src/step2_eval/step2_eval.go +++ b/go/src/step2_eval/step2_eval.go @@ -102,19 +102,38 @@ func PRINT(exp MalType) (string, error) { var repl_env = map[string]MalType{ "+": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) + a[1].(int), nil }, "-": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) - a[1].(int), nil }, "*": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) * a[1].(int), nil }, "/": func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) / a[1].(int), nil }, } +func assertArgNum(a []MalType, n int) error { + if len(a) != n { + return errors.New("wrong number of arguments") + } + return nil +} + // repl func rep(str string) (MalType, error) { var exp MalType diff --git a/go/src/step3_env/step3_env.go b/go/src/step3_env/step3_env.go index 2c0575c7..3b2e99a1 100644 --- a/go/src/step3_env/step3_env.go +++ b/go/src/step3_env/step3_env.go @@ -164,15 +164,27 @@ func rep(str string) (MalType, error) { func main() { repl_env.Set(Symbol{"+"}, func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) + a[1].(int), nil }) repl_env.Set(Symbol{"-"}, func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) - a[1].(int), nil }) repl_env.Set(Symbol{"*"}, func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) * a[1].(int), nil }) repl_env.Set(Symbol{"/"}, func(a []MalType) (MalType, error) { + if e := assertArgNum(a, 2); e != nil { + return nil, e + } return a[0].(int) / a[1].(int), nil }) @@ -195,3 +207,10 @@ func main() { fmt.Printf("%v\n", out) } } + +func assertArgNum(a []MalType, n int) error { + if len(a) != n { + return errors.New("wrong number of arguments") + } + return nil +} diff --git a/go/tests/step2_eval.mal b/go/tests/step2_eval.mal new file mode 100644 index 00000000..4b3a4bf2 --- /dev/null +++ b/go/tests/step2_eval.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(- 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(- 1 2) +;=>-1 + + +;; Testing evaluation of missing arguments +(- 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(-) +;=>Error: wrong number of arguments + diff --git a/go/tests/step3_env.mal b/go/tests/step3_env.mal new file mode 100644 index 00000000..4b3a4bf2 --- /dev/null +++ b/go/tests/step3_env.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(- 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(- 1 2) +;=>-1 + + +;; Testing evaluation of missing arguments +(- 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(-) +;=>Error: wrong number of arguments + diff --git a/go/tests/step4_if_fn_do.mal b/go/tests/step4_if_fn_do.mal new file mode 100644 index 00000000..bc9ea985 --- /dev/null +++ b/go/tests/step4_if_fn_do.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments + diff --git a/go/tests/step5_tco.mal b/go/tests/step5_tco.mal index 6fa1da6f..f5890998 100644 --- a/go/tests/step5_tco.mal +++ b/go/tests/step5_tco.mal @@ -1,2 +1,37 @@ ;; Go: skipping non-TCO recursion ;; Reason: completes even at 100,000 + +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments + diff --git a/go/tests/step6_file.mal b/go/tests/step6_file.mal new file mode 100644 index 00000000..bc9ea985 --- /dev/null +++ b/go/tests/step6_file.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments + diff --git a/go/tests/step7_quote.mal b/go/tests/step7_quote.mal new file mode 100644 index 00000000..bc9ea985 --- /dev/null +++ b/go/tests/step7_quote.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments + diff --git a/go/tests/step8_macros.mal b/go/tests/step8_macros.mal new file mode 100644 index 00000000..bc9ea985 --- /dev/null +++ b/go/tests/step8_macros.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments + diff --git a/go/tests/step9_try.mal b/go/tests/step9_try.mal new file mode 100644 index 00000000..bc9ea985 --- /dev/null +++ b/go/tests/step9_try.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments + diff --git a/go/tests/stepA_mal.mal b/go/tests/stepA_mal.mal new file mode 100644 index 00000000..bc9ea985 --- /dev/null +++ b/go/tests/stepA_mal.mal @@ -0,0 +1,34 @@ +;; Testing evaluation of excessive arguments +(+ 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(+ 1 2) +;=>3 + + +;; Testing evaluation of missing arguments +(+ 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(+) +;=>Error: wrong number of arguments + +;; Testing evaluation of excessive arguments +(= 1 2 3) +;=>Error: wrong number of arguments + +;; Valid call +(= 1 2) +;=>false + + +;; Testing evaluation of missing arguments +(= 1) +;=>Error: wrong number of arguments + +;; Testing evaluation of missing arguments +(=) +;=>Error: wrong number of arguments +