* 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
parent cf16f0de0f
commit 343c363d5b
3 changed files with 138 additions and 83 deletions

View File

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

View File

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

View File

@ -472,59 +472,15 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
start_method_dispatch:
/* method missing */
if (mn == 0) {
if (id == idMethodMissing) {
rb_bug("method missing");
}
else {
int stat = 0;
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
if (flag & VM_CALL_SUPER_BIT) {
stat |= NOEX_SUPER;
}
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;
}
}
if ((mn != 0)) {
if ((mn->nd_noex == 0)) {
/* 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);
@ -569,6 +525,57 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
}
}
}
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");
}
else {
int stat = 0;
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
if (flag & VM_CALL_SUPER_BIT) {
stat |= NOEX_SUPER;
}
val = vm_method_missing(th, id, recv, num, blockptr, stat);
}
}
RUBY_VM_CHECK_INTS();
return val;