From 2d877327e12f499ac1a0d7096f4314cc92ef228e Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 9 Feb 2021 15:39:34 -0800 Subject: Make a cyclic prepend not modify ancestors for the receiver Check for cyclic prepend before making any changes. This requires scanning the module ancestor chain twice, but in general modules do not have large numbers of ancestors. --- class.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'class.c') diff --git a/class.c b/class.c index f97956c1d3..12a67d16bc 100644 --- a/class.c +++ b/class.c @@ -1024,6 +1024,18 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(klass_origin); VALUE original_klass = klass; + if (klass_m_tbl) { + VALUE original_module = module; + + while (module) { + if (klass_m_tbl == RCLASS_M_TBL(module)) + return -1; + module = RCLASS_SUPER(module); + } + + module = original_module; + } + while (module) { int c_seen = FALSE; int superclass_seen = FALSE; @@ -1032,8 +1044,6 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) if (klass == c) { c_seen = TRUE; } - if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module)) - return -1; if (klass_origin != c || search_super) { /* ignore if the module included already in superclasses for include, * ignore if the module included before origin class for prepend -- cgit v1.2.3