Issue #15778 has been updated by Eregon (Benoit Daloze).


ko1 (Koichi Sasada) wrote:
> I heard that one advantage that current `debug_inspector` gem has is we can declare the usage of this API in Gemfile. It means that we can avoid some kind of vulnerable feature in production explicitly.

I see. Although the `rb_debug_inspector_open()` C API is still there (and could be called, e.g., via Fiddle I imagine).

`Proc#binding` in Ruby also gives access to local variables potentially far from the current method.
Similarly, `TracePoint#binding` already allows to read values from all over the program.
That's why I think it's necessary to assume that the attacker cannot call arbitrary methods.

So I think having the `caller_locations(debug: true)` API is safe enough.
If the attacker can call `caller_locations` and pass it the extra :debug argument, then I think anyway all is already lost, they might as well #eval, #system, #exit, etc.

I'd like to introduce this new keyword argument for `caller_locations`, it's one of the main features missing, and hiding it in the C API is not much of a safety, but it makes it inconvenient to use, inefficient (see above) and not portable (e.g., cannot be implemented on JRuby as a C API).

----------------------------------------
Feature #15778: Expose an API to pry-open the stack frames in Ruby
https://bugs.ruby-lang.org/issues/15778#change-80299

* Author: gsamokovarov (Genadi Samokovarov)
* Status: Open
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
* Target version: 
----------------------------------------
Hello,

I'm the maintainer of the web-console (https://github.com/rails/web-console/) gem, where one of our features is to jump between the frames in which an error occurred. To accomplish this, I currently use the Debug Inspector CRuby API. I think we should expose this functionality in Rubyland, so tools like web-console don't need to resort to C code for this. This also makes it quite harder for me to support different implementations like JRuby or TruffleRuby as everyone is having a different way to create Ruby Binding objects that represent the frames.

Here the API ideas:

Add `Thread::Backtrace::Location#binding` method that can create a binding for a specific caller of the current frame. We can reuse the existing `Kernel.caller_locations` method to generate the array of `Thread::Backtrace::Location` objects. We can optionally have the `Kernel.caller_locations(debug: true)` argument if we cannot generate the bindings lazily on the VM that can instruct the VM to do the slower operation.

- `Thread::Backtrace::Location#binding` returns `Binding|nil`. Nil result may mean that the current location is a C frame or a JITted/optimized frame and we cannot debug it.

We can also expose the DebugInspector API directly, as done in the https://github.com/banister/debug_inspector gem, but for tools like web-console, we'd need to map the bindings with the backtrace, as we cannot generate Bindings for every frame (C frames) and this needs to be done in application code, so I think the `Thread::Backtrace::Location#binding` is the better API for Ruby-land.

Such API can help us eventually write most of our debuggers in Ruby as right now we don't have a way to do Post-Mortem debugging without native code or even start our debuggers without monkey-patching `Binding`.

I have presented this idea in a RubyKaigi's 2019 talk called "Writing Debuggers in Plain Ruby", you can check-out the slides for more context: http://kaigi-debuggers-in-ruby.herokuapp.com.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>