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(+)
This commit is contained in:
nagachika 2023-07-17 16:07:39 +09:00
Родитель 8165db0f46
Коммит 5328c58c7d
4 изменённых файлов: 49 добавлений и 20 удалений

59
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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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"