From 3c3d1be9fa93dc03490b7558b214a8f8a73a323e Mon Sep 17 00:00:00 2001 From: Manef Zahra Date: Thu, 1 Feb 2024 21:42:09 -0500 Subject: [PATCH] Throw a runtime error if #binding is called from a C ext module (non-ruby frame) Co-authored-by: Randy Stauner --- CHANGELOG.md | 1 + spec/tags/optional/capi/binding_tags.txt | 1 - src/main/java/org/truffleruby/core/kernel/KernelNodes.java | 6 ++++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74fe2c50306f..c90d1f15e01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Compatibility: * Do not autosplat a proc that accepts a single positional argument and keywords (#3039, @andrykonchin). * Support passing anonymous * and ** parameters as method call arguments (#3039, @andrykonchin). * Handle either positional or keywords arguments by default in `Struct.new` (#3039, @rwstauner). +* Make `Kernel#binding` raise a RuntimeError when called from a non-Ruby frame (such as a method defined in C) (#3039, @rwstauner, @manefz) Performance: diff --git a/spec/tags/optional/capi/binding_tags.txt b/spec/tags/optional/capi/binding_tags.txt index cc3433aca16d..1112bcc66ebe 100644 --- a/spec/tags/optional/capi/binding_tags.txt +++ b/spec/tags/optional/capi/binding_tags.txt @@ -1,2 +1 @@ fails:CApiBindingSpecs Kernel#binding gives the top-most Ruby binding when called from C -fails:CApiBindingSpecs Kernel#binding raises when called from C diff --git a/src/main/java/org/truffleruby/core/kernel/KernelNodes.java b/src/main/java/org/truffleruby/core/kernel/KernelNodes.java index b1da3d150421..7f1f4c655c70 100644 --- a/src/main/java/org/truffleruby/core/kernel/KernelNodes.java +++ b/src/main/java/org/truffleruby/core/kernel/KernelNodes.java @@ -334,6 +334,12 @@ RubyBinding binding(Frame callerFrame, Object self, Object[] rubyArgs, RootCallT @Cached( value = "getAdoptedNode(this).getEncapsulatingSourceSection()", allowUncached = true, neverDefault = false) SourceSection sourceSection) { + final InternalMethod method = RubyArguments.tryGetMethod(callerFrame); + if (method == null || method.getDeclaringModule().toString().equals("Truffle::CExt")) { + throw new RaiseException(getContext(), + coreExceptions().runtimeError("You cannot call Kernel#Binding from a non-ruby frame", this)); + + } needCallerFrame(callerFrame, target); return BindingNodes.createBinding(getContext(), getLanguage(), callerFrame.materialize(), sourceSection); }