summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-09-29 13:15:04 -0700
committerJeremy Evans <code@jeremyevans.net>2019-09-29 16:28:52 -0700
commit58dfea0c8de29cbad35621847c04372b779c5f5d (patch)
tree10f03180414b703f8cddb7c18138f76e46a29712 /vm_eval.c
parent59060aadea28d3a6cd0ebbcc17c10a3628e6e867 (diff)
Make direct calls to rb_{obj_instance,mod_module}_{eval,exec} not pass keywords
In general RB_PASS_CALLED_KEYWORDS should only be set if we are sure the arguments passed come directly from Ruby. For direct calls to these C functions, we should not assume that keywords are passed. Add static *_internal versions of these functions that Kernel#instance_{eval,exec} and Module#{class,module}_{eval,exec} call that set RB_PASS_CALLED_KEYWORDS. Also, change struct.c back to calling rb_mod_module_eval, now that the call is safe.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2505
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/vm_eval.c b/vm_eval.c
index b97e3527b6..04a1315b0d 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1781,7 +1781,7 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level)
/* block eval under the class/module context */
static VALUE
-yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
+yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
{
rb_execution_context_t *ec = GET_EC();
rb_control_frame_t *cfp = ec->cfp;
@@ -1793,7 +1793,6 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
rb_cref_t *cref;
int is_lambda = FALSE;
VALUE v = 0, ret;
- int kw_splat = RB_PASS_CALLED_KEYWORDS;
v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
@@ -1865,11 +1864,11 @@ eval_under(VALUE under, VALUE self, VALUE src, VALUE file, int line)
}
static VALUE
-specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self)
+specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self, int kw_splat)
{
if (rb_block_given_p()) {
rb_check_arity(argc, 0, 0);
- return yield_under(klass, self, 1, &self);
+ return yield_under(klass, self, 1, &self, kw_splat);
}
else {
VALUE file = Qundef;
@@ -1938,11 +1937,18 @@ singleton_class_for_eval(VALUE self)
* k.instance_eval {|obj| obj == self } #=> true
*/
+static VALUE
+rb_obj_instance_eval_internal(int argc, const VALUE *argv, VALUE self)
+{
+ VALUE klass = singleton_class_for_eval(self);
+ return specific_eval(argc, argv, klass, self, RB_PASS_CALLED_KEYWORDS);
+}
+
VALUE
rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self)
{
VALUE klass = singleton_class_for_eval(self);
- return specific_eval(argc, argv, klass, self);
+ return specific_eval(argc, argv, klass, self, RB_NO_KEYWORDS);
}
/*
@@ -1963,11 +1969,18 @@ rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self)
* k.instance_exec(5) {|x| @secret+x } #=> 104
*/
+static VALUE
+rb_obj_instance_exec_internal(int argc, const VALUE *argv, VALUE self)
+{
+ VALUE klass = singleton_class_for_eval(self);
+ return yield_under(klass, self, argc, argv, RB_PASS_CALLED_KEYWORDS);
+}
+
VALUE
rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
{
VALUE klass = singleton_class_for_eval(self);
- return yield_under(klass, self, argc, argv);
+ return yield_under(klass, self, argc, argv, RB_NO_KEYWORDS);
}
/*
@@ -1997,10 +2010,16 @@ rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
* or method `code' for Thing:Class
*/
+static VALUE
+rb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod)
+{
+ return specific_eval(argc, argv, mod, mod, RB_PASS_CALLED_KEYWORDS);
+}
+
VALUE
rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
{
- return specific_eval(argc, argv, mod, mod);
+ return specific_eval(argc, argv, mod, mod, RB_NO_KEYWORDS);
}
/*
@@ -2025,10 +2044,16 @@ rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod)
* Hello there!
*/
+static VALUE
+rb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod)
+{
+ return yield_under(mod, mod, argc, argv, RB_PASS_CALLED_KEYWORDS);
+}
+
VALUE
rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod)
{
- return yield_under(mod, mod, argc, argv);
+ return yield_under(mod, mod, argc, argv, RB_NO_KEYWORDS);
}
/*
@@ -2407,8 +2432,8 @@ Init_vm_eval(void)
rb_define_global_function("loop", rb_f_loop, 0);
- rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
- rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
+ rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval_internal, -1);
+ rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec_internal, -1);
rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
#if 1
@@ -2422,10 +2447,10 @@ Init_vm_eval(void)
#endif
rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
- rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
- rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
- rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
- rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec_internal, -1);
+ rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec_internal, -1);
+ rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval_internal, -1);
+ rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval_internal, -1);
rb_eUncaughtThrow = rb_define_class("UncaughtThrowError", rb_eArgError);
rb_define_method(rb_eUncaughtThrow, "initialize", uncaught_throw_init, -1);