summaryrefslogtreecommitdiff
path: root/range.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-08-19 13:19:03 -0700
committerJeremy Evans <code@jeremyevans.net>2022-11-24 15:18:44 -0800
commit04a92a6764bf678919cf4b68a27496a39d6b886a (patch)
tree19a5548772dd56562e44f29e99f9e445f2a53eff /range.c
parentd15de2f0d73d452d1db582ab9634c3edcf77bb41 (diff)
downloadruby-04a92a6764bf678919cf4b68a27496a39d6b886a.tar.gz
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]
Diffstat (limited to 'range.c')
-rw-r--r--range.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/range.c b/range.c
index 0c3dc51c73..94b6e5a560 100644
--- a/range.c
+++ b/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;
}