Skip to content

Commit e4cc791

Browse files
committed
enum.c: check if reentered
* enum.c (cmpint_reenter_check): extract from nmin_cmp and nmin_block_cmp. * enum.c (nmin_cmp): check if reentered before rb_cmpint. [Feature #13437] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58971 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 7cdb284 commit e4cc791

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

enum.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,16 +1263,24 @@ struct nmin_data {
12631263
const char *method;
12641264
};
12651265

1266+
static VALUE
1267+
cmpint_reenter_check(struct nmin_data *data, VALUE val)
1268+
{
1269+
if (RBASIC(data->buf)->klass) {
1270+
rb_raise(rb_eRuntimeError, "%s reentered", data->method);
1271+
}
1272+
return val;
1273+
}
1274+
12661275
static int
12671276
nmin_cmp(const void *ap, const void *bp, void *_data)
12681277
{
12691278
struct cmp_opt_data cmp_opt = { 0, 0 };
12701279
struct nmin_data *data = (struct nmin_data *)_data;
12711280
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1272-
if (RBASIC(data->buf)->klass) {
1273-
rb_raise(rb_eRuntimeError, "%s reentered", data->method);
1274-
}
1281+
#define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
12751282
return OPTIMIZED_CMP(a, b, cmp_opt);
1283+
#undef rb_cmpint
12761284
}
12771285

12781286
static int
@@ -1281,13 +1289,10 @@ nmin_block_cmp(const void *ap, const void *bp, void *_data)
12811289
struct nmin_data *data = (struct nmin_data *)_data;
12821290
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
12831291
VALUE cmp = rb_yield_values(2, a, b);
1284-
if (RBASIC(data->buf)->klass) {
1285-
rb_raise(rb_eRuntimeError, "%s reentered", data->method);
1286-
}
1292+
cmpint_reenter_check(data, cmp);
12871293
return rb_cmpint(cmp, a, b);
12881294
}
12891295

1290-
12911296
static void
12921297
nmin_filter(struct nmin_data *data)
12931298
{

test/ruby/test_enum.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,22 @@ class << o; self; end.class_eval do
604604
[o, o, o].sort_by {|x| x }
605605
c.call
606606
end
607+
608+
assert_raise_with_message(RuntimeError, /reentered/) do
609+
i = 0
610+
c = nil
611+
o = Object.new
612+
class << o; self; end.class_eval do
613+
define_method(:<=>) do |x|
614+
callcc {|c2| c ||= c2 }
615+
i += 1
616+
0
617+
end
618+
end
619+
[o, o].min(1)
620+
assert_operator(i, :<=, 5, "infinite loop")
621+
c.call
622+
end
607623
end
608624

609625
def test_reverse_each

0 commit comments

Comments
 (0)