From 5328c58c7d00540f4f56749aaeefb68761bd7eba Mon Sep 17 00:00:00 2001 From: nagachika Date: Mon, 17 Jul 2023 16:07:39 +0900 Subject: merge revision(s) 1a149aab776aa6741628eb35482eff1ded197fd2,fb17c833f542222afdf482924877d43aa577782d,60f22ebf86248388b41b4ec751d16700f2b4b621: [Backport #19533] Extract range type check functions --- range.c | 55 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 19 deletions(-) [Bug #19533] Fix infinite range inclusion with numeric value --- range.c | 10 +++++++--- test/ruby/test_range.rb | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) [Bug #19533] Add spec of infinite range inclusion --- spec/ruby/core/range/case_compare_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) --- range.c | 59 +++++++++++++++++++++---------- spec/ruby/core/range/case_compare_spec.rb | 6 ++++ test/ruby/test_range.rb | 2 ++ version.h | 2 +- 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/range.c b/range.c index 6d90ecf4f3..0176e82ca3 100644 --- a/range.c +++ b/range.c @@ -1768,6 +1768,39 @@ range_include(VALUE range, VALUE val) return rb_call_super(1, &val); } +static inline bool +range_integer_edge_p(VALUE beg, VALUE end) +{ + return (!NIL_P(rb_check_to_integer(beg, "to_int")) || + !NIL_P(rb_check_to_integer(end, "to_int"))); +} + +static inline bool +range_string_edge_p(VALUE beg, VALUE end) +{ + return RB_TYPE_P(beg, T_STRING) || RB_TYPE_P(end, T_STRING); +} + +static inline bool +range_string_range_p(VALUE beg, VALUE end) +{ + return RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING); +} + +static inline VALUE +range_include_fallback(VALUE beg, VALUE end, VALUE val) +{ + if (NIL_P(beg) && NIL_P(end)) { + if (linear_object_p(val)) return Qtrue; + } + + if (NIL_P(beg) || NIL_P(end)) { + rb_raise(rb_eTypeError, "cannot determine inclusion in beginless/endless ranges"); + } + + return Qundef; +} + static VALUE range_string_cover_internal(VALUE range, VALUE val) { @@ -1776,13 +1809,11 @@ range_string_cover_internal(VALUE range, VALUE val) int nv = FIXNUM_P(beg) || FIXNUM_P(end) || linear_object_p(beg) || linear_object_p(end); - if (nv || - !NIL_P(rb_check_to_integer(beg, "to_int")) || - !NIL_P(rb_check_to_integer(end, "to_int"))) { + if (nv || range_integer_edge_p(beg, end)) { return r_cover_p(range, beg, end, val); } - else if (RB_TYPE_P(beg, T_STRING) || RB_TYPE_P(end, T_STRING)) { - if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) { + else if (range_string_edge_p(beg, end)) { + if (range_string_range_p(beg, end)) { return r_cover_p(range, beg, end, val); } if (NIL_P(beg)) { @@ -1800,11 +1831,7 @@ range_string_cover_internal(VALUE range, VALUE val) } } - if (NIL_P(beg) || NIL_P(end)) { - rb_raise(rb_eTypeError, "cannot determine inclusion in beginless/endless ranges"); - } - - return Qundef; + return range_include_fallback(beg, end, val); } static VALUE @@ -1815,20 +1842,14 @@ range_include_internal(VALUE range, VALUE val) int nv = FIXNUM_P(beg) || FIXNUM_P(end) || linear_object_p(beg) || linear_object_p(end); - if (nv || - !NIL_P(rb_check_to_integer(beg, "to_int")) || - !NIL_P(rb_check_to_integer(end, "to_int"))) { + if (nv || range_integer_edge_p(beg, end)) { return r_cover_p(range, beg, end, val); } - else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) { + else if (range_string_range_p(beg, end)) { return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range)); } - if (NIL_P(beg) || NIL_P(end)) { - rb_raise(rb_eTypeError, "cannot determine inclusion in beginless/endless ranges"); - } - - return Qundef; + return range_include_fallback(beg, end, val); } static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val); diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb index 4a3faa3163..65878aaabe 100644 --- a/spec/ruby/core/range/case_compare_spec.rb +++ b/spec/ruby/core/range/case_compare_spec.rb @@ -10,4 +10,10 @@ describe "Range#===" do it_behaves_like :range_cover_and_include, :=== it_behaves_like :range_cover, :=== + + ruby_bug "#19533", "3.2"..."3.3" do + it "returns true on any value if begin and end are both nil" do + (nil..nil).should === 1 + end + end end diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb index bb5ef6df8f..54365f1277 100644 --- a/test/ruby/test_range.rb +++ b/test/ruby/test_range.rb @@ -539,6 +539,8 @@ class TestRange < Test::Unit::TestCase assert_not_operator(0..10, :===, 11) assert_operator(5..nil, :===, 11) assert_not_operator(5..nil, :===, 0) + assert_operator(nil..10, :===, 0) + assert_operator(nil..nil, :===, 0) end def test_eqq_string diff --git a/version.h b/version.h index d250f33336..9b392f9c64 100644 --- a/version.h +++ b/version.h @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 2 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 87 +#define RUBY_PATCHLEVEL 88 #include "ruby/version.h" #include "ruby/internal/abi.h" -- cgit v1.2.3