* 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:
ko1 2007-08-25 20:56:51 +00:00
Родитель cf16f0de0f
Коммит 343c363d5b
3 изменённых файлов: 138 добавлений и 83 удалений

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

@ -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]'

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

@ -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;