diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2016-09-08 21:13:12 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2016-09-08 21:13:12 +0900 |
| commit | 08a1dd2ac89333bd928a3300f712d1a7fb57e8ff (patch) | |
| tree | e6655656d301bbf0cca0977bd5e99eab089c6079 | |
| parent | cd5133c57065d9645c125c1ce7b5dc4ce6d39bdd (diff) | |
| parent | d46702234700d6b58177829a863224b0b59d4de1 (diff) | |
| download | mruby-08a1dd2ac89333bd928a3300f712d1a7fb57e8ff.tar.gz mruby-08a1dd2ac89333bd928a3300f712d1a7fb57e8ff.zip | |
Merge pull request #3207 from ksss/splat
Fix SEGV when splat object
| -rw-r--r-- | src/array.c | 23 | ||||
| -rw-r--r-- | test/t/syntax.rb | 30 |
2 files changed, 50 insertions, 3 deletions
diff --git a/src/array.c b/src/array.c index 9b8a49584..df953832b 100644 --- a/src/array.c +++ b/src/array.c @@ -891,15 +891,32 @@ mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { + mrb_value a, recv_class; + if (mrb_array_p(v)) { return v; } - if (mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { - return mrb_funcall(mrb, v, "to_a", 0); + + if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { + return mrb_ary_new_from_values(mrb, 1, &v); } - else { + + a = mrb_funcall(mrb, v, "to_a", 0); + if (mrb_array_p(a)) { + return a; + } + else if (mrb_nil_p(a)) { return mrb_ary_new_from_values(mrb, 1, &v); } + else { + recv_class = mrb_obj_value(mrb_obj_class(mrb, v)); + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)", + recv_class, + recv_class, + mrb_obj_value(mrb_obj_class(mrb, a)) + ); + return mrb_undef_value(); + } } static mrb_value diff --git a/test/t/syntax.rb b/test/t/syntax.rb index 25ae09828..3bc68484b 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -307,6 +307,36 @@ assert('Return values of no expression case statement') do assert_equal 1, when_value end +assert('splat object in assignment') do + o = Object.new + def o.to_a + nil + end + assert_equal [o], (a = *o) + + def o.to_a + 1 + end + assert_raise(TypeError) { a = *o } + + def o.to_a + [2] + end + assert_equal [2], (a = *o) +end + +assert('splat object in case statement') do + o = Object.new + def o.to_a + nil + end + a = case o + when *o + 1 + end + assert_equal 1, a +end + assert('splat in case statement') do values = [3,5,1,7,8] testa = [1,2,7] |
