diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-04-12 03:48:48 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-04-12 03:48:48 +0000 |
commit | a72581d70f8b6d04b584d4f1ab8e115c8a5269bc (patch) | |
tree | d0c0804a644e33a8f43c4dab3861090ab3c33f13 /error.c | |
parent | fe96e87e725fe70e9c05db009326b8be02afd254 (diff) |
error.c: super in method_missing
* error.c (nometh_err_initialize): do not shirtcut rb_call_super,
to push proper control frame. [ruby-dev:50522] [Bug #14670]
* error.c (rb_nomethod_err_new): allocate and initialize a new
NoMethodError instance.
* vm_eval.c (rb_make_no_method_exception): create a new exception
instance directly without method calls, to prevent influence of
ruby level method definitions, which can cause an unpredictable
behavior, e.g., infinite recursion.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63136 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'error.c')
-rw-r--r-- | error.c | 109 |
1 files changed, 57 insertions, 52 deletions
@@ -916,6 +916,15 @@ rb_exc_new_str(VALUE etype, VALUE str) return rb_class_new_instance(1, &str, etype); } +static VALUE +exc_init(VALUE exc, VALUE mesg) +{ + rb_ivar_set(exc, id_mesg, mesg); + rb_ivar_set(exc, id_bt, Qnil); + + return exc; +} + /* * call-seq: * Exception.new(msg = nil) -> exception @@ -930,10 +939,7 @@ exc_initialize(int argc, VALUE *argv, VALUE exc) VALUE arg; rb_scan_args(argc, argv, "01", &arg); - rb_ivar_set(exc, id_mesg, arg); - rb_ivar_set(exc, id_bt, Qnil); - - return exc; + return exc_init(exc, arg); } /* @@ -1421,7 +1427,17 @@ rb_name_error_str(VALUE str, const char *fmt, ...) rb_exc_raise(exc); } -static VALUE name_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options); +static VALUE +name_err_init_attr(VALUE exc, VALUE recv, VALUE method) +{ + const rb_execution_context_t *ec = GET_EC(); + rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp); + cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp); + rb_ivar_set(exc, id_name, method); + if (recv != Qundef) rb_ivar_set(exc, id_receiver, recv); + if (cfp) rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq)); + return exc; +} /* * call-seq: @@ -1435,40 +1451,32 @@ static VALUE name_err_initialize_options(int argc, VALUE *argv, VALUE self, VALU static VALUE name_err_initialize(int argc, VALUE *argv, VALUE self) { - VALUE options; - argc = rb_scan_args(argc, argv, "*:", NULL, &options); - return name_err_initialize_options(argc, argv, self, options); -} - -static VALUE -name_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options) -{ ID keywords[1]; - VALUE values[numberof(keywords)]; - VALUE name; - VALUE iseqw = Qnil; - int i; + VALUE values[numberof(keywords)], name, options; + argc = rb_scan_args(argc, argv, "*:", NULL, &options); keywords[0] = id_receiver; rb_get_kwargs(options, keywords, 0, numberof(values), values); name = (argc > 1) ? argv[--argc] : Qnil; rb_call_super(argc, argv); - rb_ivar_set(self, id_name, name); - for (i = 0; i < numberof(keywords); ++i) { - if (values[i] != Qundef) { - rb_ivar_set(self, keywords[i], values[i]); - } - } - { - const rb_execution_context_t *ec = GET_EC(); - rb_control_frame_t *cfp = - rb_vm_get_ruby_level_next_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp)); - if (cfp) iseqw = rb_iseqw_new(cfp->iseq); - } - rb_ivar_set(self, id_iseq, iseqw); + name_err_init_attr(self, values[0], name); return self; } +static VALUE +name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method) +{ + exc_init(exc, rb_name_err_mesg_new(mesg, recv, method)); + return name_err_init_attr(exc, recv, method); +} + +VALUE +rb_name_err_new(VALUE mesg, VALUE recv, VALUE method) +{ + VALUE exc = rb_obj_alloc(rb_eNameError); + return name_err_init(exc, mesg, recv, method); +} + /* * call-seq: * name_error.name -> string or nil @@ -1506,7 +1514,13 @@ name_err_local_variables(VALUE self) return vars; } -static VALUE nometh_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options); +static VALUE +nometh_err_init_attr(VALUE exc, VALUE args, int priv) +{ + rb_ivar_set(exc, id_args, args); + rb_ivar_set(exc, id_private_call_p, priv ? Qtrue : Qfalse); + return exc; +} /* * call-seq: @@ -1521,20 +1535,22 @@ static VALUE nometh_err_initialize_options(int argc, VALUE *argv, VALUE self, VA static VALUE nometh_err_initialize(int argc, VALUE *argv, VALUE self) { - VALUE options; + int priv; + VALUE args, options; argc = rb_scan_args(argc, argv, "*:", NULL, &options); - return nometh_err_initialize_options(argc, argv, self, options); + priv = (argc > 3) && (--argc, RTEST(argv[argc])); + args = (argc > 2) ? argv[--argc] : Qnil; + if (!NIL_P(options)) argv[argc++] = options; + rb_call_super(argc, argv); + return nometh_err_init_attr(self, args, priv); } -static VALUE -nometh_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options) +VALUE +rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv) { - VALUE priv = (argc > 3) && (--argc, RTEST(argv[argc])) ? Qtrue : Qfalse; - VALUE args = (argc > 2) ? argv[--argc] : Qnil; - name_err_initialize_options(argc, argv, self, options); - rb_ivar_set(self, id_args, args); - rb_ivar_set(self, id_private_call_p, priv); - return self; + VALUE exc = rb_obj_alloc(rb_eNoMethodError); + name_err_init(exc, mesg, recv, method); + return nometh_err_init_attr(exc, args, priv); } /* :nodoc: */ @@ -1584,17 +1600,6 @@ rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method) return result; } -VALUE -rb_name_err_new(VALUE mesg, VALUE recv, VALUE method) -{ - VALUE exc = rb_obj_alloc(rb_eNameError); - rb_ivar_set(exc, id_mesg, rb_name_err_mesg_new(mesg, recv, method)); - rb_ivar_set(exc, id_bt, Qnil); - rb_ivar_set(exc, id_name, method); - rb_ivar_set(exc, id_receiver, recv); - return exc; -} - /* :nodoc: */ static VALUE name_err_mesg_equal(VALUE obj1, VALUE obj2) |