From ad18d1297ed82aa9c38375532b0b709131cf1ae7 Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Fri, 16 Dec 2022 13:32:13 +0900 Subject: Reject keyword arguments given to Enumerator::Product.new The use of keyword arguments should be reserved for future extension. --- enumerator.c | 33 +++++++++++++++++++++++---------- test/ruby/test_enumerator.rb | 8 ++++++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/enumerator.c b/enumerator.c index a0c51b585c..5cbaaee04b 100644 --- a/enumerator.c +++ b/enumerator.c @@ -20,6 +20,7 @@ #include "id.h" #include "internal.h" +#include "internal/class.h" #include "internal/enumerator.h" #include "internal/error.h" #include "internal/hash.h" @@ -3481,9 +3482,16 @@ enum_product_allocate(VALUE klass) * e.size #=> 6 */ static VALUE -enum_product_initialize(VALUE obj, VALUE enums) +enum_product_initialize(int argc, VALUE *argv, VALUE obj) { struct enum_product *ptr; + VALUE enums = Qnil, options = Qnil; + + rb_scan_args(argc, argv, "*:", &enums, &options); + + if (!NIL_P(options) && !RHASH_EMPTY_P(options)) { + rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options))); + } rb_check_frozen(obj); TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr); @@ -3697,16 +3705,21 @@ enum_product_inspect(VALUE obj) * e.size #=> 6 */ static VALUE -enumerator_s_product(VALUE klass, VALUE enums) +enumerator_s_product(int argc, VALUE *argv, VALUE klass) { - VALUE obj = enum_product_initialize(enum_product_allocate(rb_cEnumProduct), enums); + VALUE enums = Qnil, options = Qnil, block = Qnil; - if (rb_block_given_p()) { - return enum_product_run(obj, rb_block_proc()); - } - else { - return obj; + rb_scan_args(argc, argv, "*:&", &enums, &options, &block); + + if (!NIL_P(options) && !RHASH_EMPTY_P(options)) { + rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options))); } + + VALUE obj = enum_product_initialize(argc, argv, enum_product_allocate(rb_cEnumProduct)); + + if (NIL_P(block)) return obj; + + return enum_product_run(obj, block); } /* @@ -4586,7 +4599,7 @@ InitVM_Enumerator(void) /* Product */ rb_cEnumProduct = rb_define_class_under(rb_cEnumerator, "Product", rb_cEnumerator); rb_define_alloc_func(rb_cEnumProduct, enum_product_allocate); - rb_define_method(rb_cEnumProduct, "initialize", enum_product_initialize, -2); + rb_define_method(rb_cEnumProduct, "initialize", enum_product_initialize, -1); rb_define_method(rb_cEnumProduct, "initialize_copy", enum_product_init_copy, 1); rb_define_method(rb_cEnumProduct, "each", enum_product_each, 0); rb_define_method(rb_cEnumProduct, "size", enum_product_size, 0); @@ -4597,7 +4610,7 @@ InitVM_Enumerator(void) rb_undef_method(rb_cEnumProduct, "next_values"); rb_undef_method(rb_cEnumProduct, "peek"); rb_undef_method(rb_cEnumProduct, "peek_values"); - rb_define_singleton_method(rb_cEnumerator, "product", enumerator_s_product, -2); + rb_define_singleton_method(rb_cEnumerator, "product", enumerator_s_product, -1); /* ArithmeticSequence */ rb_cArithSeq = rb_define_class_under(rb_cEnumerator, "ArithmeticSequence", rb_cEnumerator); diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index 3ca33126d5..d448d62bd5 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -924,6 +924,10 @@ class TestEnumerator < Test::Unit::TestCase e.each { |*x| elts << x } assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"], [3, "a"], [3, "b"]], elts + assert_raise(ArgumentError) { + Enumerator::Product.new(1..3, foo: 1, bar: 2) + } + e = Enumerator.product(1..3, %w[a b]) assert_instance_of(Enumerator::Product, e) @@ -943,5 +947,9 @@ class TestEnumerator < Test::Unit::TestCase e = Enumerator.product(1..3, Enumerator.new { |y| y << 'a' << 'b' }) assert_equal(nil, e.size) assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"]], e.take(4) + + assert_raise(ArgumentError) { + Enumerator.product(1..3, foo: 1, bar: 2) + } end end -- cgit v1.2.1