object.c: fix searching nested const paths

* object.c (rb_mod_const_get, rb_mod_const_defined): nested const
  paths should not search from toplevel constants.
  [ruby-core:92202] [Bug #15758]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67472 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2019-04-08 13:47:37 +00:00
Родитель e1b592b508
Коммит d10451f3fd
2 изменённых файлов: 34 добавлений и 7 удалений

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

@ -2526,7 +2526,19 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
name = ID2SYM(id); name = ID2SYM(id);
goto wrong_name; goto wrong_name;
} }
mod = RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id); #if 0
mod = rb_const_get_0(mod, id, beglen > 0 || !RTEST(recur), RTEST(recur), FALSE);
#else
if (!RTEST(recur)) {
mod = rb_const_get_at(mod, id);
}
else if (beglen == 0) {
mod = rb_const_get(mod, id);
}
else {
mod = rb_const_get_from(mod, id);
}
#endif
} }
return mod; return mod;
@ -2674,16 +2686,27 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
name = ID2SYM(id); name = ID2SYM(id);
goto wrong_name; goto wrong_name;
} }
if (RTEST(recur)) {
if (!rb_const_defined(mod, id)) #if 0
return Qfalse; mod = rb_const_search(mod, id, beglen > 0 || !RTEST(recur), RTEST(recur), FALSE);
mod = rb_const_get(mod, id); if (mod == Qundef) return Qfalse;
} #else
else { if (!RTEST(recur)) {
if (!rb_const_defined_at(mod, id)) if (!rb_const_defined_at(mod, id))
return Qfalse; return Qfalse;
mod = rb_const_get_at(mod, id); mod = rb_const_get_at(mod, id);
} }
else if (beglen == 0) {
if (!rb_const_defined(mod, id))
return Qfalse;
mod = rb_const_get(mod, id);
}
else {
if (!rb_const_defined_from(mod, id))
return Qfalse;
mod = rb_const_get_from(mod, id);
}
#endif
if (p < pend && !RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) { if (p < pend && !RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module", rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",

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

@ -296,6 +296,9 @@ class TestModule < Test::Unit::TestCase
def test_nested_get def test_nested_get
assert_equal Other, Object.const_get([self.class, 'Other'].join('::')) assert_equal Other, Object.const_get([self.class, 'Other'].join('::'))
assert_equal User::USER, self.class.const_get([User, 'USER'].join('::')) assert_equal User::USER, self.class.const_get([User, 'USER'].join('::'))
assert_raise(NameError) {
Object.const_get([self.class.name, 'String'].join('::'))
}
end end
def test_nested_get_symbol def test_nested_get_symbol
@ -328,6 +331,7 @@ class TestModule < Test::Unit::TestCase
assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')]) assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')])
assert_send([self.class, :const_defined?, 'User::USER']) assert_send([self.class, :const_defined?, 'User::USER'])
assert_not_send([self.class, :const_defined?, 'User::Foo']) assert_not_send([self.class, :const_defined?, 'User::Foo'])
assert_not_send([Object, :const_defined?, [self.class.name, 'String'].join('::')])
end end
def test_nested_defined_symbol def test_nested_defined_symbol