1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Properly resolve refinements in defined? on private call [Bug #16932]

This commit is contained in:
Nobuyoshi Nakada 2020-06-03 23:06:06 +09:00
parent 8340c773e5
commit 184f78314e
Notes: git 2020-06-04 02:13:23 +09:00
4 changed files with 34 additions and 4 deletions

View file

@ -95,6 +95,12 @@ MJIT_SYMBOL_EXPORT_BEGIN
void rb_vm_search_method_slowpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass);
MJIT_SYMBOL_EXPORT_END
/* vm_method.c */
struct rb_execution_context_struct;
MJIT_SYMBOL_EXPORT_BEGIN
int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID id, int priv);
MJIT_SYMBOL_EXPORT_END
/* vm_dump.c */
void rb_print_backtrace(void);

View file

@ -309,24 +309,45 @@ class TestDefined < Test::Unit::TestCase
refine RefinedClass do
def pub
end
private
def priv
end
end
def self.call_without_using(x = RefinedClass.new)
defined?(x.pub)
end
def self.vcall_without_using(x = RefinedClass.new)
x.instance_eval {defined?(priv)}
end
using self
def self.call_with_using(x = RefinedClass.new)
defined?(x.pub)
end
def self.vcall_with_using(x = RefinedClass.new)
x.instance_eval {defined?(priv)}
end
end
def test_defined_refined_call_without_using
assert(!RefiningModule.call_without_using, "refined public method without using")
end
def test_defined_refined_vcall_without_using
assert(!RefiningModule.vcall_without_using, "refined private method without using")
end
def test_defined_refined_call_with_using
assert(RefiningModule.call_with_using, "refined public method with using")
end
def test_defined_refined_vcall_with_using
assert(RefiningModule.vcall_with_using, "refined private method with using")
end
end

View file

@ -3651,12 +3651,9 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_
}
case DEFINED_FUNC:
klass = CLASS_OF(v);
if (rb_method_boundp(klass, SYM2ID(obj), 0)) {
if (rb_ec_obj_respond_to(ec, v, SYM2ID(obj), TRUE)) {
expr_type = DEFINED_METHOD;
}
else {
expr_type = check_respond_to_missing(obj, v);
}
break;
case DEFINED_METHOD:{
VALUE klass = CLASS_OF(v);

View file

@ -2358,6 +2358,12 @@ int
rb_obj_respond_to(VALUE obj, ID id, int priv)
{
rb_execution_context_t *ec = GET_EC();
return rb_ec_obj_respond_to(ec, obj, id, priv);
}
int
rb_ec_obj_respond_to(rb_execution_context_t *ec, VALUE obj, ID id, int priv)
{
VALUE klass = CLASS_OF(obj);
int ret = vm_respond_to(ec, klass, obj, id, priv);
if (ret == -1) ret = basic_obj_respond_to(ec, obj, id, !priv);