[#108771] [Ruby master Bug#18816] Ractor segfaulting MacOS 12.4 (aarch64 / M1 processor) — "brodock (Gabriel Mazetto)" <noreply@...>

Issue #18816 has been reported by brodock (Gabriel Mazetto).

8 messages 2022/06/05

[#108802] [Ruby master Feature#18821] Expose Pattern Matching interfaces in core classes — "baweaver (Brandon Weaver)" <noreply@...>

Issue #18821 has been reported by baweaver (Brandon Weaver).

9 messages 2022/06/08

[#108822] [Ruby master Feature#18822] Ruby lack a proper method to percent-encode strings for URIs (RFC 3986) — "byroot (Jean Boussier)" <noreply@...>

Issue #18822 has been reported by byroot (Jean Boussier).

18 messages 2022/06/09

[#108937] [Ruby master Bug#18832] Suspicious superclass mismatch — "fxn (Xavier Noria)" <noreply@...>

Issue #18832 has been reported by fxn (Xavier Noria).

16 messages 2022/06/15

[#108976] [Ruby master Misc#18836] DevMeeting-2022-07-21 — "mame (Yusuke Endoh)" <noreply@...>

Issue #18836 has been reported by mame (Yusuke Endoh).

12 messages 2022/06/17

[#109043] [Ruby master Bug#18876] OpenSSL is not available with `--with-openssl-dir` — "Gloomy_meng (Gloomy Meng)" <noreply@...>

Issue #18876 has been reported by Gloomy_meng (Gloomy Meng).

18 messages 2022/06/23

[#109052] [Ruby master Bug#18878] parse.y: Foo::Bar {} is inconsistently rejected — "qnighy (Masaki Hara)" <noreply@...>

Issue #18878 has been reported by qnighy (Masaki Hara).

9 messages 2022/06/26

[#109055] [Ruby master Bug#18881] IO#read_nonblock raises IOError when called following buffered character IO — "javanthropus (Jeremy Bopp)" <noreply@...>

Issue #18881 has been reported by javanthropus (Jeremy Bopp).

9 messages 2022/06/26

[#109063] [Ruby master Bug#18882] File.read cuts off a text file with special characters when reading it on MS Windows — magynhard <noreply@...>

Issue #18882 has been reported by magynhard (Matth辰us Johannes Beyrle).

15 messages 2022/06/27

[#109081] [Ruby master Feature#18885] Long lived fork advisory API (potential Copy on Write optimizations) — "byroot (Jean Boussier)" <noreply@...>

Issue #18885 has been reported by byroot (Jean Boussier).

23 messages 2022/06/28

[#109083] [Ruby master Bug#18886] Struct aref and aset don't trigger any tracepoints. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18886 has been reported by ioquatix (Samuel Williams).

8 messages 2022/06/29

[#109095] [Ruby master Misc#18888] Migrate ruby-lang.org mail services to Google Domains and Google Workspace — "shugo (Shugo Maeda)" <noreply@...>

Issue #18888 has been reported by shugo (Shugo Maeda).

16 messages 2022/06/30

[ruby-core:108919] [Ruby master Bug#18780] Incorrect binding receiver for C API rb_eval_string()

From: "alanwu (Alan Wu)" <noreply@...>
Date: 2022-06-14 21:12:27 UTC
List: ruby-core #108919
Issue #18780 has been updated by alanwu (Alan Wu).


Thanks for the bug report. The "binding with mixed information from two
contexts" situation from <https://bugs.ruby-lang.org/issues/18780#note-4>
definitely looks wrong. I wrote a reproducer and luckily, it's no
longer an issue on the master branch (ab10f111c3).

> Let's say I need to write a myEval method which is like eval, but first
> prints out the string that is eval'd. ... You have just made this literally
> impossible to write in ruby.

This is in fact possible with the `rb_binding_new()` API on both 2.7.6 and on
the master branch. Here is a demo script:

```ruby
puts RUBY_DESCRIPTION

require 'tmpdir'
require 'rbconfig'

# From https://gist.github.com/eregon/31259907c132ab61e9f136d684b1fc39
# courtesy of Benoit.
def inline_c_extension(c_code)
  Dir.mktmpdir('inline_c_extension') do |dir|
    File.write("#{dir}/cext.c", c_code)
    File.write("#{dir}/extconf.rb", <<~RUBY)
      require 'mkmf'
      create_makefile('cext')
    RUBY

    out = IO.popen([RbConfig.ruby, 'extconf.rb'], chdir: dir, &:read)
    raise "ruby extconf.rb failed: #{$?.inspect}\n#{out}" unless $?.success?

    out = IO.popen(['make'], chdir: dir, &:read)
    raise "make failed: #{$?.inspect}\n#{out}" unless $?.success?

    require "#{dir}/cext.#{RbConfig::CONFIG['DLEXT']}"
  end
end

inline_c_extension <<~C
#include "ruby.h"

// A wrapped version of Kernel#eval that prints the program before evaluating.
// Uses the caller's Ruby context just like Kernel#eval.
static VALUE
my_eval(VALUE self, VALUE program)
{
    ID p_id = rb_intern("p");
    ID eval_id = rb_intern("eval");
    VALUE binding;

    if (1 /* do what I understand OP wants */) {
        binding = rb_binding_new();
    }
    else {
        // Flip the if to check the "impossible binding" issue from [ruby-core:108597]
        binding = rb_eval_string("p [:rbeval_string, @foo, foo]; binding");
    }

    rb_funcall(self, p_id, 1, program);
    return rb_funcall(binding, eval_id, 1, program);
}

void
Init_cext(void)
{
    rb_define_global_function("my_eval", my_eval, 1);
}
C

@foo = :main
foo = :mainl
my_eval("p [:in_main, self, @foo, foo]")

class Foo
  def foo
    @foo = :inclass
    foo = :inclassl
    my_eval("p [:inside_foo, self, @foo, foo]")
  end

  new.foo
end

```

```shell
$ ruby demo.rb
ruby 3.2.0dev (2022-06-14T16:06:06Z master ab10f111c3) [x86_64-darwin21]
"p [:in_main, self, @foo, foo]"
[:in_main, main, :main, :mainl]
"p [:inside_foo, self, @foo, foo]"
[:inside_foo, #<Foo:0x000000010fcc1360 @foo=:inclass>, :inclass, :inclassl]
```

In terms of [#18487], `my_eval` in the demo is not any more powerful than
`Kernel#binding` and `Kernel#eval` since it's only getting the binding of
the Ruby frame immediately below it.

By the way, thanks to some awesome work by @shyouhei, newer versions of public C headers
have API documentations. I would recommend reading those docs instead of the implementation.
For example for `rb_eval_string()`:

    /**
     * Evaluates the given string in an isolated binding.
     *
     * Here  "isolated"  means  that  the   binding  does  not  inherit  any  other
     * bindings.  This behaves same as the binding for required libraries.
     * ...

I wonder if we host the HTML version of the C API docs anywhere...


----------------------------------------
Bug #18780: Incorrect binding receiver for C API rb_eval_string()
https://bugs.ruby-lang.org/issues/18780#change-98004

* Author: daveola (David Stellar)
* Status: Rejected
* Priority: Normal
* ruby -v: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------

% ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]

(Though looking at the source code this problem still exists in ruby 3.0)


The rb_eval_string() is seemingly capable of everything that eval is capable of, with one slight deviation.  The binding is oddly setup to be correct except for the receiver/self.

This means that while these both act the same:

  ruby:    eval("puts someLocalVariable")
  C API:   rb_eval_string("puts someLocalVariable")

These do not:

  ruby:   eval("puts @someInstanceVar")
  C API:  rb_eval_string("puts @someInstanceVar")    # nil

And this is because these do not work:

  ruby:   eval("puts self")                          # self of calling context
  ruby:   eval("puts binding().receiver")            # self of calling context
  C API:  rb_eval_string("puts self")                # main
  C API:  rb_eval_string("puts binding().receiver")  # main

We can see the problem in the MRI source in ruby_eval_string_from_file() which has:

    return eval_string_with_cref(rb_vm_top_self(), rb_str_new2(str), NULL, file, 1);

We've passed in rb_vm_top_self instead of the correct 'self'

Although possibly the issue is in the API itself with the fact that there's no way to plumb through the receiver that you are given in the C extension method function call, i.e.:

        // My C extension that calls eval and knows what it's 'self' is.
        VALUE method_myCMethod(int argc, VALUE *argv, VALUE self) {
                rb_eval_string("...");  // <- no way to be given self?
        }

Having said that, rb_eval_string is able to determine the vast majority of the binding context, since it correctly builds the binding() object *except* that the receiver is set to main, so perhaps this is something that *can* be determined.  It is something that the builtin eval is able to do, after all.  So possibly this is just a failure with MRI.  I don't have other rubies to test.  (I'm on ruby 2.7.0 but the source relevant to this hasn't changed.)

I would argue this is a bug, because we are essentially given a corrupted result from binding() - one where we may have access to the local variables of an instance method, but one where the self itself is not properly set.  That's not an actual legit binding state in the ruby code.




-- 
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>

In This Thread