[ruby-core:120920] [Ruby master Bug#21125] Kernel is called first
From:
"jeremyevans0 (Jeremy Evans) via ruby-core" <ruby-core@...>
Date:
2025-02-09 02:45:24 UTC
List:
ruby-core #120920
Issue #21125 has been updated by jeremyevans0 (Jeremy Evans).
Assignee set to tenderlovemaking (Aaron Patterson)
The reason this works in Ruby 3.3 and below is that `system` is a private method and not a public method, and calls to private methods where the receiver is not `self` call `method_missing`. `raw.system` is a method call where the receiver is not `self`, but `Kernel#system` is a private method, so this should be calling `method_missing`. The fact that `method_missing` is not called in Ruby 3.4 is a bug. I've determined the bug is in generic argument forwarding. If you switch `...` (generic argument forwarding) to `*, **, &` (anonymous splat usage), things work correctly. Assigning to @tenderlovemaking.
----------------------------------------
Bug #21125: Kernel is called first
https://bugs.ruby-lang.org/issues/21125#change-111802
* Author: mikik0 (Hashino Mikiko)
* Status: Open
* Assignee: tenderlovemaking (Aaron Patterson)
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
Kernel#system is being called when there is a column or method name named system.
The other methods of Kernel reproduce the problem.
Ex.Rand returns a random value, and exit terminates the program.
## Reproducible script:
``` ruby
class ObjectifiedHash
def initialize(hash)
@hash = hash
end
private
attr_reader :hash
def method_missing(method_name, *args, &block)
if hash.key?(method_name.to_sym)
hash[method_name.to_sym]
else
super
end
end
def respond_to_missing?(method_name, include_private = false)
hash.key?(method_name.to_sym) || super
end
end
class Foo
def system(...)
# Kernel#system is called
raw.system(...)
# (...) passes if there is no
# raw.system
end
def initialize(raw)
@raw = raw
end
def get_system
system
end
private
attr_reader :raw
end
class Test
def self.run
obj = ObjectifiedHash.new({
system: 'system'
})
foo = Foo.new(obj)
# foo.system would pass.
# After executing foo.system, hoge.get_system also passes.
# p foo.system
p foo.get_system
end
end
Test.run
```
## Execution Results
``` shell
hoge.rb:26:in 'Kernel#system': wrong number of arguments (given 0, expected 1+) (ArgumentError)
raw.system(...)
^^^
from ruby.rb:26:in 'Foo#system'
from ruby.rb:36:in 'Foo#get_system'
from ruby.rb:54:in 'Test.run'
from ruby.rb:58:in '<main>'
```
## Expected results
``` shell
"system"
```
PR that may be relevant: https://github.com/ruby/ruby/pull/11028
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/