summaryrefslogtreecommitdiff
path: root/error.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-12 03:48:48 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-12 03:48:48 +0000
commita72581d70f8b6d04b584d4f1ab8e115c8a5269bc (patch)
treed0c0804a644e33a8f43c4dab3861090ab3c33f13 /error.c
parentfe96e87e725fe70e9c05db009326b8be02afd254 (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.c109
1 files changed, 57 insertions, 52 deletions
diff --git a/error.c b/error.c
index c8b9404c63..6dce0c8601 100644
--- a/error.c
+++ b/error.c
@@ -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)