mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Only allow procs created by Symbol#to_proc to call public methods
Fixes [Bug #18826] Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
This commit is contained in:
parent
d115a06037
commit
bfa6a8ddc8
Notes:
git
2022-08-11 05:02:39 +09:00
Merged: https://github.com/ruby/ruby/pull/6018 Merged-By: jeremyevans <code@jeremyevans.net>
3 changed files with 57 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
||||||
raise 'should be run without RubyGems' if defined?(Gem)
|
raise 'should be run without RubyGems' if defined?(Gem)
|
||||||
|
|
||||||
def deprecated(n=1)
|
public def deprecated(n=1)
|
||||||
# puts nil, caller(0), nil
|
# puts nil, caller(0), nil
|
||||||
warn "use X instead", uplevel: n
|
warn "use X instead", uplevel: n
|
||||||
end
|
end
|
||||||
|
|
|
@ -46,6 +46,33 @@ describe "Symbol#to_proc" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ruby_version_is "3.2" do
|
||||||
|
it "only calls public methods" do
|
||||||
|
body = proc do
|
||||||
|
public def pub; @a << :pub end
|
||||||
|
protected def pro; @a << :pro end
|
||||||
|
private def pri; @a << :pri end
|
||||||
|
attr_reader :a
|
||||||
|
end
|
||||||
|
|
||||||
|
@a = []
|
||||||
|
singleton_class.class_eval(&body)
|
||||||
|
tap(&:pub)
|
||||||
|
proc{tap(&:pro)}.should raise_error(NoMethodError)
|
||||||
|
proc{tap(&:pri)}.should raise_error(NoMethodError)
|
||||||
|
@a.should == [:pub]
|
||||||
|
|
||||||
|
@a = []
|
||||||
|
c = Class.new(&body)
|
||||||
|
o = c.new
|
||||||
|
o.instance_variable_set(:@a, [])
|
||||||
|
o.tap(&:pub)
|
||||||
|
proc{tap(&:pro)}.should raise_error(NoMethodError)
|
||||||
|
proc{o.tap(&:pri)}.should raise_error(NoMethodError)
|
||||||
|
o.a.should == [:pub]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "raises an ArgumentError when calling #call on the Proc without receiver" do
|
it "raises an ArgumentError when calling #call on the Proc without receiver" do
|
||||||
-> {
|
-> {
|
||||||
:object_id.to_proc.call
|
:object_id.to_proc.call
|
||||||
|
|
|
@ -3182,9 +3182,11 @@ ci_missing_reason(const struct rb_callinfo *ci)
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling);
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
||||||
struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE symbol)
|
struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE symbol, int flags)
|
||||||
{
|
{
|
||||||
ASSUME(calling->argc >= 0);
|
ASSUME(calling->argc >= 0);
|
||||||
/* Also assumes CALLER_SETUP_ARG is already done. */
|
/* Also assumes CALLER_SETUP_ARG is already done. */
|
||||||
|
@ -3194,9 +3196,7 @@ vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
||||||
VALUE recv = calling->recv;
|
VALUE recv = calling->recv;
|
||||||
VALUE klass = CLASS_OF(recv);
|
VALUE klass = CLASS_OF(recv);
|
||||||
ID mid = rb_check_id(&symbol);
|
ID mid = rb_check_id(&symbol);
|
||||||
int flags = VM_CALL_FCALL |
|
flags |= VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
|
||||||
VM_CALL_OPT_SEND |
|
|
||||||
(calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
|
|
||||||
|
|
||||||
if (UNLIKELY(! mid)) {
|
if (UNLIKELY(! mid)) {
|
||||||
mid = idMethodMissing;
|
mid = idMethodMissing;
|
||||||
|
@ -3243,9 +3243,31 @@ vm_call_symbol(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
||||||
{ .method_missing_reason = missing_reason },
|
{ .method_missing_reason = missing_reason },
|
||||||
rb_callable_method_entry_with_refinements(klass, mid, NULL));
|
rb_callable_method_entry_with_refinements(klass, mid, NULL));
|
||||||
|
|
||||||
|
if (flags & VM_CALL_FCALL) {
|
||||||
return vm_call_method(ec, reg_cfp, calling);
|
return vm_call_method(ec, reg_cfp, calling);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct rb_callcache *cc = calling->cc;
|
||||||
|
VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
|
||||||
|
|
||||||
|
if (vm_cc_cme(cc) != NULL) {
|
||||||
|
switch (METHOD_ENTRY_VISI(vm_cc_cme(cc))) {
|
||||||
|
case METHOD_VISI_PUBLIC: /* likely */
|
||||||
|
return vm_call_method_each_type(ec, reg_cfp, calling);
|
||||||
|
case METHOD_VISI_PRIVATE:
|
||||||
|
vm_cc_method_missing_reason_set(cc, MISSING_PRIVATE);
|
||||||
|
case METHOD_VISI_PROTECTED:
|
||||||
|
vm_cc_method_missing_reason_set(cc, MISSING_PROTECTED);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VM_UNREACHABLE(vm_call_method);
|
||||||
|
}
|
||||||
|
return vm_call_method_missing(ec, reg_cfp, calling);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm_call_method_nome(ec, reg_cfp, calling);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling)
|
vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling)
|
||||||
{
|
{
|
||||||
|
@ -3283,7 +3305,7 @@ vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
|
||||||
calling->argc -= 1;
|
calling->argc -= 1;
|
||||||
DEC_SP(1);
|
DEC_SP(1);
|
||||||
|
|
||||||
return vm_call_symbol(ec, reg_cfp, calling, calling->ci, sym);
|
return vm_call_symbol(ec, reg_cfp, calling, calling->ci, sym, VM_CALL_FCALL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4097,7 +4119,7 @@ vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
||||||
VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
|
VALUE symbol = VM_BH_TO_SYMBOL(block_handler);
|
||||||
CALLER_SETUP_ARG(reg_cfp, calling, ci);
|
CALLER_SETUP_ARG(reg_cfp, calling, ci);
|
||||||
calling->recv = TOPN(--calling->argc);
|
calling->recv = TOPN(--calling->argc);
|
||||||
return vm_call_symbol(ec, reg_cfp, calling, ci, symbol);
|
return vm_call_symbol(ec, reg_cfp, calling, ci, symbol, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue