Issue #20096 has been reported by jay4rubydev (Jay M).
----------------------------------------
Bug #20096: Ruby 3.2.2 win32/registry: Junk appended to Windows Registry String Value
https://bugs.ruby-lang.org/issues/20096
* Author: jay4rubydev (Jay M)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mswin64_140]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Ruby Version:
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mswin64_140]
Compiler: MSVC 2019 - Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30147 for x64.
Issue: win32/registry adds junk to Windows Registry String Value
Code:
require 'win32/registry'
win_oracle_key = "SOFTWARE\\MicroSoft"
reg=Win32::Registry::HKEY_LOCAL_MACHINE.open(win_oracle_key, Win32::Registry::KEY_ALL_ACCESS)
inst_loc_key = "inst_loc"
inv_dir="C:\\Program Files\\Tester\\ModuleInfo"
reg[inst_loc_key] = inv_dir
Result:
Registry contains:
C:\Program Files\Tester\ModuleInfo爀
Observation: Looks like memory overread
Expected Result - without the junk:
C:\Program Files\Tester\ModuleInfo
After changing the code in registry.rb:
From:
def write(name, type, data)
termsize = 0
case type
when REG_SZ, REG_EXPAND_SZ
data = data.encode(WCHAR)
termsize = WCHAR_SIZE
To:
def write(name, type, data)
termsize = 0
case type
when REG_SZ, REG_EXPAND_SZ
enc_data = data.encode(WCHAR)
# Add NULL WCHAR for string data and don't set the termsize because
# enc_data.bytesize will now include the size of the NULL character.
enc_data += WCHAR_NUL
# termsize = WCHAR_SIZE
...
--
https://bugs.ruby-lang.org/
Issue #18035 has been updated by ioquatix (Samuel Williams).
I encountered this issue recently:
https://bugs.ruby-lang.org/issues/17159
I think immutability would cover these types of problems too. I think it would be worthwhile discussing the merits of shareability vs immutability as a baseline model that we expect people to build on.
----------------------------------------
Feature #18035: Introduce general model/semantic for immutability.
https://bugs.ruby-lang.org/issues/18035#change-107137
* Author: ioquatix (Samuel Williams)
* Status: Open
----------------------------------------
It would be good to establish some rules around mutability, immutability, frozen, and deep frozen in Ruby.
I see time and time again, incorrect assumptions about how this works in production code. Constants that aren't really constant, people using `#freeze` incorrectly, etc.
I don't have any particular preference but:
- We should establish consistent patterns where possible, e.g.
- Objects created by `new` are mutable.
- Objects created by literal are immutable.
We have problems with how `freeze` works on composite data types, e.g. `Hash#freeze` does not impact children keys/values, same for Array. Do we need to introduce `freeze(true)` or `#deep_freeze` or some other method?
Because of this, frozen does not necessarily correspond to immutable. This is an issue which causes real world problems.
I also propose to codify this where possible, in terms of "this class of object is immutable" should be enforced by the language/runtime, e.g.
```ruby
module Immutable
def new(...)
super.freeze
end
end
class MyImmutableObject
extend Immutable
def initialize(x)
@x = x
end
def freeze
return self if frozen?
@x.freeze
super
end
end
o = MyImmutableObject.new([1, 2, 3])
puts o.frozen?
```
Finally, this area has an impact to thread and fiber safe programming, so it is becoming more relevant and I believe that the current approach which is rather adhoc is insufficient.
I know that it's non-trivial to retrofit existing code, but maybe it can be done via magic comment, etc, which we already did for frozen string literals.
Proposed PR: https://github.com/ruby/ruby/pull/4879
--
https://bugs.ruby-lang.org/
Issue #20314 has been reported by mame (Yusuke Endoh).
----------------------------------------
Bug #20314: Simultaneous Timeout expires may raise an exception after the block
https://bugs.ruby-lang.org/issues/20314
* Author: mame (Yusuke Endoh)
* Status: Open
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Launchable reports `TestTimeout#test_nested_timeout` as a flaky test, and I reproduced it as follows.
```ruby
require "timeout"
class A < Exception
end
class B < Exception
end
begin
Timeout.timeout(0.1, A) do
Timeout.timeout(0.1, B) do
nil while true
end
end
rescue A, B
p $! #=> #<A: execution expired>
# Exception B is raised after the above call returns
#=> test.rb:16:in `p': execution expired (B)
p :end # not reach
end
```
This is because the timer thread performs two consecutive `Thread#raise` to the target thread.
I have discussed this with @ko1 and have come up with three solutions.
### Solution 1
When multiple nested Timeouts expire simultaneously, raise an exception for the outer-most Timeout and let the inner Timeouts expire without throwing an exception. In the above example, it would only raise A.
The problem with this approach is that if you are rescuing A in the inner block, it may never ends:
```ruby
Timeout.timeout(0.1, A) do
Timeout.timeout(0.1, B) do
begin
sleep
rescue A
sleep # The exception A is caught. The inner Timeout is already expired, so the code (may) never end.
end
end
end
```
Note that, if A and B did not occur at the same time, it would raise B. This is a race condition.
### Solution 2
When multiple nested Timeouts expire simultaneously, raise an exception for the inner-most Timeout and let the outer Timeouts wait until the inner-most Timeout returns. In the above example, it would raise either A or B, not both.
The problem with this approach is that if you are rescuing B in the inner block, it never ends:
```ruby
Timeout.timeout(0.1, A) do
Timeout.timeout(0.1, B) do
begin
sleep
rescue B
sleep # The outer Timeout waits for the inner timeout, and the inner Timeout never return. So this code never ends.
end
end
end
```
### Solution 3
Make thread interrupt queue one length. If the target thread has already been `Thread#raise(A)`, the new `Thread#raise(B)` blocks until the target thread processes A.
Since there will be no more simultaneous Thread#raise, there will be no more exceptions after the end of the block. The timeout timer thread should be changed in consideration that `Thread#raise` may block.
--
https://bugs.ruby-lang.org/
Issue #20317 has been reported by tenderlovemaking (Aaron Patterson).
----------------------------------------
Feature #20317: Removing the `allocate` method should cause `new` to fail
https://bugs.ruby-lang.org/issues/20317
* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
----------------------------------------
When you remove the `allocate` method from a class the you can't allocate the class via the `allocate` method. However, you _can_ allocate the class via the `new` method:
```ruby
class Foo; end
Foo.singleton_class.undef_method(:allocate)
begin
Foo.allocate # doesn't work, of course
rescue NoMethodError
end
begin
Class.instance_method(:allocate).bind_call(Foo) # also doesn't work
rescue TypeError
end
Foo.new # works?
```
I think that when we remove the `allocate` method, the `new` method should also fail as there is no `allocate` method for `new` to call.
--
https://bugs.ruby-lang.org/
Issue #20232 has been reported by fxn (Xavier Noria).
----------------------------------------
Misc #20232: Document Kernel#require and Module#autoload concurrency guarantees
https://bugs.ruby-lang.org/issues/20232
* Author: fxn (Xavier Noria)
* Status: Open
* Priority: Normal
----------------------------------------
I'd like to document `Kernel#require` and `Module#autoload` concurrency guarantees.
In the case of multiple threads loading the same file concurrently, `Kernel#require` will succeed in just one of them and the rest will wait and return false. If a constant that has an autoload is concurrently referenced, the same can be said. Assuming no errors, only one thread will succeed, and the rest wait. There will be no context switching in the middle of an autoload that will result in a `NameError` in other threads waiting for that constant.
Now, I'd like to have a discussion about those guarantees with fibers.
In the case of manually managed fibers, users can enter a deadlock by hand:
```ruby
# This produces a deadlock.
File.write('/tmp/bar.rb', <<~RUBY)
Fiber.yield
RUBY
Fiber.new { require '/tmp/bar.rb' }.resume
Fiber.new { require '/tmp/bar.rb' }.resume
```
If this is expected, I guess users should be told this is a possibility in the API dosc? Because from a user perspective, you don't really have elements to anticipate a deadlock there if the docs don't warn you.
A similar deadlock can be triggered with an `autoload` instead of a `require`:
```ruby
# This produces a deadlock.
File.write('/tmp/bar.rb', <<~RUBY)
Fiber.yield
Bar = 1
RUBY
autoload :Bar, '/tmp/bar.rb'
Fiber.new { Bar }.resume
Fiber.new { Bar }.resume
```
A different matter is fibers managed by fiber schedulers. I have not been able to enter a deadlock with the fiber schedulers I have tried, but from the point of view of the user, doing something like I/O or sleeping at the top-level is not unlike that manual `Fiber.yield` above. The contract for fiber schedulers is mostly an interface, but it does not address this, at least in an explicit way. Do fiber schedulers guarantee anything about this with the current contract?
I'd be glad to volunteer docs with the conclusions of this thread.
--
https://bugs.ruby-lang.org/
Issue #20324 has been reported by kyanagi (Kouhei Yanagita).
----------------------------------------
Bug #20324: `(1..).overlap?('foo'..)` returns true
https://bugs.ruby-lang.org/issues/20324
* Author: kyanagi (Kouhei Yanagita)
* Status: Open
* ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin22]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
While thinking about finding the intersection of two ranges, I found that `(1..).overlap?('foo'..)` returns true.
In the current implementation, it seems that `(a..).overlap?(b..)` or `(..a).overlap?(..b)` returns true regardless of what `a` or `b` are.
However, I think it should return true if and only if `a` and `b` are comparable.
(What is the intersection of `1..` and `'foo'..`?)
--
https://bugs.ruby-lang.org/
Issue #20307 has been reported by nobu (Nobuyoshi Nakada).
----------------------------------------
Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys
https://bugs.ruby-lang.org/issues/20307
* Author: nobu (Nobuyoshi Nakada)
* Status: Open
* Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED
----------------------------------------
I don't think this behavior is expected.
```ruby
i = Hash.new.compare_by_identity
k = "a"
i[k] = 0
h = {}.update(i)
p h["a"] # => 0
k.upcase!
p h.fetch(k) # in 'Hash#fetch': key not found: "A" (KeyError)
```
--
https://bugs.ruby-lang.org/
Hi folks!
it's my pleasure to introduce myself here and invite you to join us for EuRuKo in Bosnia & Herzegovina this September, as the first-ever Ruby conference in the country.
You can find more information about the conference here: https://2024.euruko.org/
My name is Muhamed Isabegovic, I've been a Rubyist since 2016 and I managed to win the community vote to organize EuRuKo in my country.
Registrations are not ready, I am hoping we kick them off during March.
I will write to this thread once that happens as well, however that shouldn't stop me from inviting you to join EuRuKo free of charge.
Similar as for RubyKaigi (text is copied from that thread), all Ruby core team members (who have direct
commit access to the Git repo) are invited to the conference with free
admission.
If you are interested in joining us, please send an e-mail to organisers(a)euruko.org from one of the e-mails listed on the committer e-mail list -> https://github.com/ruby/ruby-commit-hook/blob/master/config/email.yml , so we can identify you as Ruby core. Once we setup the platform with tickets, you will receive an invitation which will enable you to login and join the conference in-person free of charge.
(another steal from RubyKaigi:)
Also, EuRuKo wants talk proposals from true Ruby hackers like you
who are reading this message. Our CFP form is already open, and will
be closed April 15th!
So if you have anything in your mind that you want to share with the
audience there, please submit and we'll be happy to review.
https://www.papercall.io/euruko2024
--
Muhamed Isabegovic, Host of EuRuKo 2024