Raise TypeError for endless non-numeric range include?
Beginless ranges previously raised TypeError for this case, except for string ranges, which had unexpected behavior: ('a'..'z').include?('ww') # false (..'z').include?('ww') # previously true, now TypeError Use of include? with endless ranges could previously result in an infinite loop. This splits off a range_string_cover_internal function from range_include_internal. Fixes [Bug #18580]
This commit is contained in:
parent
d15de2f0d7
commit
04a92a6764
Notes:
git
2022-11-24 23:19:02 +00:00
49
range.c
49
range.c
@ -1679,7 +1679,9 @@ range_inspect(VALUE range)
|
||||
return rb_exec_recursive(inspect_range, range, 0);
|
||||
}
|
||||
|
||||
static VALUE range_include_internal(VALUE range, VALUE val, int string_use_cover);
|
||||
static VALUE range_include_internal(VALUE range, VALUE val);
|
||||
static VALUE range_string_cover_internal(VALUE range, VALUE val);
|
||||
VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
@ -1723,7 +1725,7 @@ static VALUE range_include_internal(VALUE range, VALUE val, int string_use_cover
|
||||
static VALUE
|
||||
range_eqq(VALUE range, VALUE val)
|
||||
{
|
||||
VALUE ret = range_include_internal(range, val, 1);
|
||||
VALUE ret = range_string_cover_internal(range, val);
|
||||
if (!UNDEF_P(ret)) return ret;
|
||||
return r_cover_p(range, RANGE_BEG(range), RANGE_END(range), val);
|
||||
}
|
||||
@ -1763,13 +1765,13 @@ range_eqq(VALUE range, VALUE val)
|
||||
static VALUE
|
||||
range_include(VALUE range, VALUE val)
|
||||
{
|
||||
VALUE ret = range_include_internal(range, val, 0);
|
||||
VALUE ret = range_include_internal(range, val);
|
||||
if (!UNDEF_P(ret)) return ret;
|
||||
return rb_call_super(1, &val);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_include_internal(VALUE range, VALUE val, int string_use_cover)
|
||||
range_string_cover_internal(VALUE range, VALUE val)
|
||||
{
|
||||
VALUE beg = RANGE_BEG(range);
|
||||
VALUE end = RANGE_END(range);
|
||||
@ -1783,15 +1785,9 @@ range_include_internal(VALUE range, VALUE val, int string_use_cover)
|
||||
}
|
||||
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)) {
|
||||
if (string_use_cover) {
|
||||
return r_cover_p(range, beg, end, val);
|
||||
}
|
||||
else {
|
||||
VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
|
||||
return rb_str_include_range_p(beg, end, val, RANGE_EXCL(range));
|
||||
}
|
||||
return r_cover_p(range, beg, end, val);
|
||||
}
|
||||
else if (NIL_P(beg)) {
|
||||
if (NIL_P(beg)) {
|
||||
VALUE r = rb_funcall(val, id_cmp, 1, end);
|
||||
if (NIL_P(r)) return Qfalse;
|
||||
if (RANGE_EXCL(range)) {
|
||||
@ -1805,6 +1801,35 @@ range_include_internal(VALUE range, VALUE val, int string_use_cover)
|
||||
return RBOOL(rb_cmpint(r, beg, val) <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (NIL_P(beg) || NIL_P(end)) {
|
||||
rb_raise(rb_eTypeError, "cannot determine inclusion in beginless/endless ranges");
|
||||
}
|
||||
|
||||
return Qundef;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
range_include_internal(VALUE range, VALUE val)
|
||||
{
|
||||
VALUE beg = RANGE_BEG(range);
|
||||
VALUE end = RANGE_END(range);
|
||||
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"))) {
|
||||
return r_cover_p(range, beg, end, val);
|
||||
}
|
||||
else if (RB_TYPE_P(beg, T_STRING) && RB_TYPE_P(end, T_STRING)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -546,7 +546,7 @@ class TestRange < Test::Unit::TestCase
|
||||
assert_not_operator('A'..'Z', :===, 'ana')
|
||||
assert_operator('A'.., :===, 'ANA')
|
||||
assert_operator(..'Z', :===, 'ANA')
|
||||
assert_operator(nil..nil, :===, 'ANA')
|
||||
assert_raise(TypeError) {(nil..nil) === 'ANA'}
|
||||
end
|
||||
|
||||
def test_eqq_time
|
||||
@ -599,13 +599,14 @@ class TestRange < Test::Unit::TestCase
|
||||
assert_include("a"..."z", "y")
|
||||
assert_not_include("a"..."z", "z")
|
||||
assert_not_include("a".."z", "cc")
|
||||
assert_include("a".., "c")
|
||||
assert_not_include("a".., "5")
|
||||
assert_raise(TypeError) {("a"..).include?("c")}
|
||||
assert_raise(TypeError) {("a"..).include?("5")}
|
||||
|
||||
assert_include(0...10, 5)
|
||||
assert_include(5..., 10)
|
||||
assert_not_include(5..., 0)
|
||||
assert_include(.."z", "z")
|
||||
assert_not_include(..."z", "z")
|
||||
assert_raise(TypeError) {(.."z").include?("z")}
|
||||
assert_raise(TypeError) {(..."z").include?("z")}
|
||||
assert_include(..10, 10)
|
||||
assert_not_include(...10, 10)
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user