summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-09-14 01:49:33 -0700
committerJeremy Evans <code@jeremyevans.net>2019-09-14 01:49:33 -0700
commitb78a345bd63ff2b52ea0f84754ab0988748a9bd0 (patch)
treed529df7726d15a14d21c7b03a99b332dc93ba7d3 /vm_eval.c
parentb2c29bbab6e88253f497fc3e66a43cb7b4d425b5 (diff)
Only set RB_PASS_CALLED_KEYWORDS in C functions called directly from Ruby
It is not safe to set this in C functions that can be called from other C functions, as in the non argument-delegation case, you can end up calling a Ruby method with a flag indicating keywords are set without passing keywords. Introduce some new *_kw functions that take a kw_splat flag and use these functions to set RB_PASS_CALLED_KEYWORDS in places where we know we are delegating methods (e.g. Class#new, Method#call)
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 68a724834e..f1246537e7 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -269,7 +269,7 @@ rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const
}
static inline VALUE
-vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv)
+vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat)
{
VALUE recv = ec->cfp->self;
VALUE klass;
@@ -290,16 +290,25 @@ vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv)
return method_missing(recv, id, argc, argv, MISSING_SUPER);
}
else {
- return rb_vm_call0(ec, recv, id, argc, argv, me, RB_PASS_CALLED_KEYWORDS);
+ add_empty_keyword(&argc, &argv, &kw_splat);
+ return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
}
}
VALUE
+rb_call_super_kw(int argc, const VALUE *argv, int kw_splat)
+{
+ rb_execution_context_t *ec = GET_EC();
+ PASS_PASSED_BLOCK_HANDLER_EC(ec);
+ return vm_call_super(ec, argc, argv, kw_splat);
+}
+
+VALUE
rb_call_super(int argc, const VALUE *argv)
{
rb_execution_context_t *ec = GET_EC();
PASS_PASSED_BLOCK_HANDLER_EC(ec);
- return vm_call_super(ec, argc, argv);
+ return vm_call_super(ec, argc, argv, RB_NO_KEYWORDS);
}
VALUE