Project

General

Profile

Bug #4438 ยป 0001-check-rescue-clause-arguments.patch

nobu (Nobuyoshi Nakada), 08/06/2012 10:33 PM

View differences:

compile.c
case NODE_ARGSPUSH:
only_special_literals = 0;
COMPILE(cond_seq, "when/cond splat", vals);
ADD_INSN1(cond_seq, nd_line(vals), checkincludearray, Qtrue);
ADD_INSN1(cond_seq, nd_line(vals), checkincludearray, INT2FIX(0));
ADD_INSNL(cond_seq, nd_line(vals), branchif, l1);
break;
default:
......
case NODE_ARGSPUSH:
ADD_INSN(ret, nd_line(vals), putnil);
COMPILE(ret, "when2/cond splat", vals);
ADD_INSN1(ret, nd_line(vals), checkincludearray, Qfalse);
ADD_INSN1(ret, nd_line(vals), checkincludearray, INT2FIX(1));
ADD_INSN(ret, nd_line(vals), pop);
ADD_INSNL(ret, nd_line(vals), branchif, l1);
break;
......
switch (nd_type(narg)) {
case NODE_ARRAY:
while (narg) {
ADD_INSN1(ret, nd_line(narg), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
COMPILE(ret, "rescue arg", narg->nd_head);
ADD_SEND(ret, nd_line(narg), ID2SYM(id_core_check_rescuable), INT2FIX(1));
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
ADD_INSNL(ret, nd_line(node), branchif, label_hit);
......
case NODE_ARGSPUSH:
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
COMPILE(ret, "rescue/cond splat", narg);
ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue);
ADD_INSN1(ret, nd_line(node), checkincludearray, INT2FIX(2));
ADD_INSN(ret, nd_line(node), swap);
ADD_INSN(ret, nd_line(node), pop);
ADD_INSNL(ret, nd_line(node), branchif, label_hit);
id.c
REGISTER_SYMID(id_core_hash_merge_ary, "core#hash_merge_ary");
REGISTER_SYMID(id_core_hash_merge_ptr, "core#hash_merge_ptr");
REGISTER_SYMID(id_core_hash_merge_kwd, "core#hash_merge_kwd");
REGISTER_SYMID(id_core_check_rescuable, "core#check_rescuable");
REGISTER_SYMID(idEach, "each");
REGISTER_SYMID(idLength, "length");
insns.def
ary = rb_Array(ary);
}
if (flag == Qtrue) {
switch (flag) {
case INT2FIX(0):
/* NODE_CASE */
for (i = 0; i < RARRAY_LEN(ary); i++) {
/* TODO: fix me (use another method dispatch) */
......
break;
}
}
}
else {
break;
case INT2FIX(1):
obj = Qfalse;
/* NODE_WHEN */
for (i = 0; i < RARRAY_LEN(ary); i++) {
......
break;
}
}
break;
case INT2FIX(2):
/* NODE_RESBODY */
for (i = 0; i < RARRAY_LEN(ary); i++) {
void rb_vm_error_invalid_rescue(VALUE);
VALUE mod = RARRAY_PTR(ary)[i];
if (!rb_obj_is_kind_of(mod, rb_cModule)) {
rb_vm_error_invalid_rescue(mod);
}
if (RTEST(rb_funcall2(mod, idEqq, 1, &obj))) {
result = Qtrue;
break;
}
}
break;
}
}
parse.y
%nonassoc id_core_hash_merge_ary
%nonassoc id_core_hash_merge_ptr
%nonassoc id_core_hash_merge_kwd
%nonassoc id_core_check_rescuable
%token tLAST_TOKEN
test/ruby/test_exception.rb
end
end
Bug4438 = '[ruby-core:35364]'
def test_rescue_single_argument
assert_raise(TypeError, Bug4438) do
begin
raise
rescue 1
end
end
end
def test_rescue_splat_argument
assert_raise(TypeError, Bug4438) do
begin
raise
rescue *Array(1)
end
end
end
def test_raise_with_wrong_number_of_arguments
assert_raise(TypeError) { raise nil }
assert_raise(TypeError) { raise 1, 1 }
vm.c
return hash;
}
void
rb_vm_error_invalid_rescue(VALUE mod)
{
rb_raise(rb_eTypeError, "class or module required for rescue clause");
}
static VALUE
m_core_check_rescuable(VALUE recv, VALUE mod)
{
if (!rb_obj_is_kind_of(mod, rb_cModule)) {
vm_pop_frame(GET_THREAD());
rb_vm_error_invalid_rescue(mod);
}
return mod;
}
extern VALUE *rb_gc_stack_start;
extern size_t rb_gc_stack_maxsize;
#ifdef __ia64
......
rb_define_method_id(klass, id_core_hash_merge_ary, m_core_hash_merge_ary, 2);
rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1);
rb_define_method_id(klass, id_core_hash_merge_kwd, m_core_hash_merge_kwd, 2);
rb_define_method_id(klass, id_core_check_rescuable, m_core_check_rescuable, 1);
rb_obj_freeze(fcore);
rb_gc_register_mark_object(fcore);
rb_mRubyVMFrozenCore = fcore;
    (1-1/1)