diff --git a/CHANGELOG.md b/CHANGELOG.md index 74fe2c50306..c90d1f15e01 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 cc3433aca16..1112bcc66eb 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 b1da3d15042..7f1f4c655c7 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); }