зеркало из https://github.com/github/ruby.git
* insnhelper.ci (vm_call_method): fix to relaxant safe level check
($SAFE > 2). [ruby-core:11998] * bootstraptest/test_method.rb: add tests for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13275 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
cf16f0de0f
Коммит
343c363d5b
|
@ -1,3 +1,10 @@
|
|||
Sun Aug 26 05:54:49 2007 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* insnhelper.ci (vm_call_method): fix to relaxant safe level check
|
||||
($SAFE > 2). [ruby-core:11998]
|
||||
|
||||
* bootstraptest/test_method.rb: add tests for above.
|
||||
|
||||
Sun Aug 26 05:52:08 2007 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* test/ruby/test_fiber.rb: fix to require 'continuation'.
|
||||
|
|
|
@ -916,3 +916,44 @@ assert_equal 'ok', %q{
|
|||
end
|
||||
C.new.m
|
||||
}
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
proc{
|
||||
$SAFE = 1
|
||||
class C
|
||||
def m
|
||||
:ok
|
||||
end
|
||||
end
|
||||
}.call
|
||||
C.new.m
|
||||
}, '[ruby-core:11998]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
proc{
|
||||
$SAFE = 2
|
||||
class C
|
||||
def m
|
||||
:ok
|
||||
end
|
||||
end
|
||||
}.call
|
||||
C.new.m
|
||||
}, '[ruby-core:11998]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
proc{
|
||||
$SAFE = 3
|
||||
class C
|
||||
def m
|
||||
:ng
|
||||
end
|
||||
end
|
||||
}.call
|
||||
begin
|
||||
C.new.m
|
||||
rescue SecurityError
|
||||
:ok
|
||||
end
|
||||
}, '[ruby-core:11998]'
|
||||
|
||||
|
|
173
insnhelper.ci
173
insnhelper.ci
|
@ -472,8 +472,96 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
|
||||
start_method_dispatch:
|
||||
|
||||
/* method missing */
|
||||
if (mn == 0) {
|
||||
if ((mn != 0)) {
|
||||
if ((mn->nd_noex == 0)) {
|
||||
/* dispatch method */
|
||||
NODE *node;
|
||||
|
||||
normal_method_dispatch:
|
||||
|
||||
node = mn->nd_body;
|
||||
|
||||
switch (nd_type(node)) {
|
||||
case RUBY_VM_METHOD_NODE:{
|
||||
vm_setup_method(th, cfp, num, blockptr, flag, (VALUE)node->nd_body, recv, klass);
|
||||
return Qundef;
|
||||
}
|
||||
case NODE_CFUNC:{
|
||||
val = vm_call_cfunc(th, cfp, num, id, recv, klass, node, blockptr);
|
||||
break;
|
||||
}
|
||||
case NODE_ATTRSET:{
|
||||
val = rb_ivar_set(recv, node->nd_vid, *(cfp->sp - 1));
|
||||
cfp->sp -= 2;
|
||||
break;
|
||||
}
|
||||
case NODE_IVAR:{
|
||||
val = rb_ivar_get(recv, node->nd_vid);
|
||||
cfp->sp -= 1;
|
||||
break;
|
||||
}
|
||||
case NODE_BMETHOD:{
|
||||
VALUE *argv = cfp->sp - num;
|
||||
val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv);
|
||||
cfp->sp += - num - 1;
|
||||
break;
|
||||
}
|
||||
case NODE_ZSUPER:{
|
||||
klass = RCLASS(mn->nd_clss)->super;
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
if (mn != 0) {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
else {
|
||||
goto start_method_dispatch;
|
||||
}
|
||||
}
|
||||
default:{
|
||||
printf("node: %s\n", ruby_node_name(nd_type(node)));
|
||||
rb_bug("eval_invoke_method: unreachable");
|
||||
/* unreachable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int noex_safe;
|
||||
|
||||
if (!(flag & VM_CALL_FCALL_BIT) &&
|
||||
(mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) {
|
||||
int stat = NOEX_PRIVATE;
|
||||
|
||||
if (flag & VM_CALL_VCALL_BIT) {
|
||||
stat |= NOEX_VCALL;
|
||||
}
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) {
|
||||
VALUE defined_class = mn->nd_clss;
|
||||
|
||||
if (TYPE(defined_class) == T_ICLASS) {
|
||||
defined_class = RBASIC(defined_class)->klass;
|
||||
}
|
||||
|
||||
if (!rb_obj_is_kind_of(cfp->self, rb_class_real(defined_class))) {
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
|
||||
}
|
||||
else {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
}
|
||||
else if ((noex_safe = NOEX_SAFE(mn->nd_noex)) > th->safe_level &&
|
||||
(noex_safe > 2)) {
|
||||
rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id));
|
||||
}
|
||||
else {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* method missing */
|
||||
if (id == idMethodMissing) {
|
||||
rb_bug("method missing");
|
||||
}
|
||||
|
@ -488,87 +576,6 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
}
|
||||
else if (UNLIKELY(mn->nd_noex)) {
|
||||
if (!(flag & VM_CALL_FCALL_BIT) &&
|
||||
(mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) {
|
||||
int stat = NOEX_PRIVATE;
|
||||
if (flag & VM_CALL_VCALL_BIT) {
|
||||
stat |= NOEX_VCALL;
|
||||
}
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
||||
}
|
||||
else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) {
|
||||
VALUE defined_class = mn->nd_clss;
|
||||
|
||||
if (TYPE(defined_class) == T_ICLASS) {
|
||||
defined_class = RBASIC(defined_class)->klass;
|
||||
}
|
||||
|
||||
if (!rb_obj_is_kind_of(cfp->self, rb_class_real(defined_class))) {
|
||||
val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
|
||||
}
|
||||
else {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
}
|
||||
else if (NOEX_SAFE(mn->nd_noex) > th->safe_level) {
|
||||
rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id));
|
||||
}
|
||||
else {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
}
|
||||
|
||||
/* dispatch method */
|
||||
else {
|
||||
NODE *node;
|
||||
normal_method_dispatch:
|
||||
|
||||
node = mn->nd_body;
|
||||
switch (nd_type(node)) {
|
||||
case RUBY_VM_METHOD_NODE:{
|
||||
vm_setup_method(th, cfp, num, blockptr, flag, (VALUE)node->nd_body, recv, klass);
|
||||
return Qundef;
|
||||
}
|
||||
case NODE_CFUNC:{
|
||||
val = vm_call_cfunc(th, cfp, num, id, recv, klass, node, blockptr);
|
||||
break;
|
||||
}
|
||||
case NODE_ATTRSET:{
|
||||
val = rb_ivar_set(recv, node->nd_vid, *(cfp->sp - 1));
|
||||
cfp->sp -= 2;
|
||||
break;
|
||||
}
|
||||
case NODE_IVAR:{
|
||||
val = rb_ivar_get(recv, node->nd_vid);
|
||||
cfp->sp -= 1;
|
||||
break;
|
||||
}
|
||||
case NODE_BMETHOD:{
|
||||
VALUE *argv = cfp->sp - num;
|
||||
val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv);
|
||||
cfp->sp += - num - 1;
|
||||
break;
|
||||
}
|
||||
case NODE_ZSUPER:{
|
||||
klass = RCLASS(mn->nd_clss)->super;
|
||||
mn = rb_method_node(klass, id);
|
||||
|
||||
if (mn != 0) {
|
||||
goto normal_method_dispatch;
|
||||
}
|
||||
else {
|
||||
goto start_method_dispatch;
|
||||
}
|
||||
}
|
||||
default:{
|
||||
printf("node: %s\n", ruby_node_name(nd_type(node)));
|
||||
rb_bug("eval_invoke_method: unreachable");
|
||||
/* unreachable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RUBY_VM_CHECK_INTS();
|
||||
return val;
|
||||
|
|
Загрузка…
Ссылка в новой задаче