Issue #19542 has been reported by hanazuki (Kasumi Hanazuki).
----------------------------------------
Bug #19542: Operations on zero-sized IO::Buffer are raising
https://bugs.ruby-lang.org/issues/19542
* Author: hanazuki (Kasumi Hanazuki)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
I found that IO::Buffer of zero length is not cloneable.
```
% ruby -v
ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux]
% ruby -e 'p IO::Buffer.for("").dup'
-e:1:in `initialize_copy': The buffer is not allocated! (IO::Buffer::AllocationError)
from -e:1:in `initialize_dup'
from -e:1:in `dup'
from -e:1:in `<main>'
% ruby -e 'p IO::Buffer.new(0).dup'
-e:1: warning: IO::Buffer is experimental and both the Ruby and C interface may change in the future!
-e:1:in `initialize_copy': The buffer is not allocated! (IO::Buffer::AllocationError)
from -e:1:in `initialize_dup'
from -e:1:in `dup'
from -e:1:in `<main>'
```
It seems `IO::Buffer.new(0)` allocates no memory for buffer on object creation and thus prohibits reading from or writing to it. So `#dup` method copying zero bytes into the new IO::Buffer raises the exception.
Empty buffers, however, often appear in corner cases of usual operations (encrypting an empty string, encoding an empty list of items into binary, etc.) and it would be easy if such cases could be handled consistently.
Other operations on NULL IO::Buffers are also useful but currently raising.
```
IO::Buffer.new(0) <=> IO::Buffer.new(1)
IO::Buffer.new(0).each(:U8).to_a
IO::Buffer.new(0).get_values([], 0)
IO::Buffer.new(0).set_values([], 0, [])
```
I'm not sure this is a bug or by design, but at least I don't want cloning and comparison to raise.
--
https://bugs.ruby-lang.org/
Issue #20169 has been reported by ko1 (Koichi Sasada).
----------------------------------------
Bug #20169: `GC.compact` can raises `EFAULT` on IO
https://bugs.ruby-lang.org/issues/20169
* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
1. `GC.compact` introduces read barriers to detect read accesses to the pages.
2. I/O operations release GVL to pass the control while their execution, and another thread can call `GC.compact` (or auto compact feature I guess, but not checked yet).
3. Call `write(ptr)` can return `EFAULT` when `GC.compact` is running because `ptr` points read-barrier protected pages.
Reproducible steps:
Apply the following patch to increase possibility:
```patch
diff --git a/io.c b/io.c
index f6cd2c1a56..83d67ba2dc 100644
--- a/io.c
+++ b/io.c
@@ -1212,8 +1212,12 @@ internal_write_func(void *ptr)
}
}
+ int cnt = 0;
retry:
- do_write_retry(write(iis->fd, iis->buf, iis->capa));
+ for (; cnt < 1000; cnt++) {
+ do_write_retry(write(iis->fd, iis->buf, iis->capa));
+ if (result <= 0) break;
+ }
if (result < 0 && !iis->nonblock) {
int e = errno;
```
Run the following code:
```ruby
t1 = Thread.new{ 10_000.times.map{"#{_1}"}; GC.compact while true }
t2 = Thread.new{
i=0
$stdout.write "<#{i+=1}>" while true
}
t2.join
```
and
```
$ make run
(snip)
4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4><4>#<Thread:0x00007fa61b4dd758 ../../src/trunk/test.rb:3 run> terminated with exception (report_on_exception is true):
../../src/trunk/test.rb:5:in `write': Bad address @ io_write - <STDOUT> (Errno::EFAULT)
from ../../src/trunk/test.rb:5:in `block in <main>'
../../src/trunk/test.rb:5:in `write': Bad address @ io_write - <STDOUT> (Errno::EFAULT)
from ../../src/trunk/test.rb:5:in `block in <main>'
make: *** [uncommon.mk:1383: run] Error 1
```
I think this is why we get `EFAULT` on CI. To increase possibilities running many busy processes (`ruby -e 'loop{}'` for example) will help (and on CI environment there are such busy processes accidentally).
--
https://bugs.ruby-lang.org/
Issue #20178 has been reported by jhawthorn (John Hawthorn).
----------------------------------------
Bug #20178: Out of bounds stack read on Array#first when built with -O0
https://bugs.ruby-lang.org/issues/20178
* Author: jhawthorn (John Hawthorn)
* Status: Open
* Priority: Normal
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: REQUIRED
----------------------------------------
https://github.com/ruby/ruby/pull/9499
Previously on builds with optimizations disabled, we could end up with an out of bounds read trying to access a non-existent local variable in the compiled `Primitive.cexpr!`.
This occurred only when we had all of:
* built with `-O0`
* Leaf builtin
* `Primitive.mandatory_only`
* "no args builtin", called by [vm_call_single_noarg_inline_builtin](https://github.com/ruby/ruby/pull/7486)
* The stack is escaped to the heap via binding or a proc
This is because `mk_builtin_loader` generated reads for all locals regardless of whether they were used and in the case we generated a mandatory_only iseq that would include more variables than were actually available.
On optimized builds, the invalid accesses would be optimized away, and this also was often unnoticed as the invalid access would just hit another part of the stack unless it had been escaped to the heap. However we should fix (and backport) this both because and so that we can use ASAN and debug builds.
---
``` ruby
def foo
binding
[].first
end
foo
foo
```
```
=================================================================
==1542964==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000045fc8 at pc 0x55cb2958b7d0 bp 0x7ffcdc9f1f00 sp 0x7ffcdc9f1ef0
READ of size 8 at 0x603000045fc8 thread T0
#0 0x55cb2958b7cf in rb_vm_lvar /home/jhawthorn/src/ruby/builtin.h:103
#1 0x55cb295ab586 in builtin_inline_class_104 /home/jhawthorn/src/ruby/array.rbinc:14
#2 0x55cb29b2243e in builtin_invoker0 /home/jhawthorn/src/ruby/vm_insnhelper.c:6724
#3 0x55cb29b09556 in vm_call_single_noarg_inline_builtin /home/jhawthorn/src/ruby/vm_insnhelper.c:2931
#4 0x55cb29b1d112 in vm_sendish /home/jhawthorn/src/ruby/vm_insnhelper.c:5581
#5 0x55cb29b34533 in vm_exec_core /home/jhawthorn/src/ruby/insns.def:834
#6 0x55cb29b6c9a3 in rb_vm_exec /home/jhawthorn/src/ruby/vm.c:2487
#7 0x55cb29b6f338 in rb_iseq_eval_main /home/jhawthorn/src/ruby/vm.c:2753
#8 0x55cb296f7188 in rb_ec_exec_node /home/jhawthorn/src/ruby/eval.c:287
#9 0x55cb296f74e4 in ruby_run_node /home/jhawthorn/src/ruby/eval.c:328
#10 0x55cb29587d51 in rb_main main.c:39
#11 0x55cb29587eb1 in main main.c:58
#12 0x7f3295558ccf (/usr/lib/libc.so.6+0x27ccf) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
#13 0x7f3295558d89 in __libc_start_main (/usr/lib/libc.so.6+0x27d89) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
#14 0x55cb29587bb4 in _start (/home/jhawthorn/src/ruby/miniruby+0x1a7bb4) (BuildId: acaf2fc9526d3e1423a2fcbd072ee6aeb3e5c4c6)
0x603000045fc8 is located 8 bytes before 32-byte region [0x603000045fd0,0x603000045ff0)
allocated by thread T0 here:
#0 0x7f32958e1359 in __interceptor_malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x55cb2975348a in objspace_xmalloc0 /home/jhawthorn/src/ruby/gc.c:12625
#2 0x55cb29753940 in ruby_xmalloc2_body /home/jhawthorn/src/ruby/gc.c:12872
#3 0x55cb29759643 in ruby_xmalloc2 /home/jhawthorn/src/ruby/gc.c:14473
#4 0x55cb29b62b80 in vm_make_env_each /home/jhawthorn/src/ruby/vm.c:977
#5 0x55cb29b62dc0 in vm_make_env_object /home/jhawthorn/src/ruby/vm.c:1010
#6 0x55cb29b65271 in rb_vm_make_binding /home/jhawthorn/src/ruby/vm.c:1433
#7 0x55cb298cbdb5 in rb_binding_new /home/jhawthorn/src/ruby/proc.c:347
#8 0x55cb298cbdc8 in rb_f_binding /home/jhawthorn/src/ruby/proc.c:397
#9 0x55cb29b0ca60 in ractor_safe_call_cfunc_0 /home/jhawthorn/src/ruby/vm_insnhelper.c:3306
#10 0x55cb29b0eb89 in vm_call_cfunc_with_frame_ /home/jhawthorn/src/ruby/vm_insnhelper.c:3490
#11 0x55cb29b0f149 in vm_call_cfunc_with_frame /home/jhawthorn/src/ruby/vm_insnhelper.c:3518
#12 0x55cb29b1d112 in vm_sendish /home/jhawthorn/src/ruby/vm_insnhelper.c:5581
#13 0x55cb29b34533 in vm_exec_core /home/jhawthorn/src/ruby/insns.def:834
#14 0x55cb29b6c9a3 in rb_vm_exec /home/jhawthorn/src/ruby/vm.c:2487
#15 0x55cb29b6f338 in rb_iseq_eval_main /home/jhawthorn/src/ruby/vm.c:2753
#16 0x55cb296f7188 in rb_ec_exec_node /home/jhawthorn/src/ruby/eval.c:287
#17 0x55cb296f74e4 in ruby_run_node /home/jhawthorn/src/ruby/eval.c:328
#18 0x55cb29587d51 in rb_main main.c:39
#19 0x55cb29587eb1 in main main.c:58
#20 0x7f3295558ccf (/usr/lib/libc.so.6+0x27ccf) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/jhawthorn/src/ruby/builtin.h:103 in rb_vm_lvar
Shadow bytes around the buggy address:
0x603000045d00: fd fd fd fa fa fa fd fd fd fa fa fa 00 00 00 00
0x603000045d80: fa fa 00 00 04 fa fa fa fd fd fd fd fa fa 00 00
0x603000045e00: 00 00 fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
0x603000045e80: 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00 00 00
0x603000045f00: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
=>0x603000045f80: 00 00 fa fa 00 00 00 00 fa[fa]00 00 00 00 fa fa
0x603000046000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x603000046080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x603000046100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x603000046180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x603000046200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==1542964==ABORTING
```
--
https://bugs.ruby-lang.org/
Issue #20172 has been reported by mwaldvogel (Michael Waldvogel).
----------------------------------------
Bug #20172: Socket.addrinfo failing randomly
https://bugs.ruby-lang.org/issues/20172
* Author: mwaldvogel (Michael Waldvogel)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
I've recently updated one of my linux systems (Gentoo) to glibc 2.38 (that was the only change). After the update most of the time the below error happens. Among other things this breaks rubygems for me. I've reinstalled ruby 3.2.2 with rvm and didn't encounter the issue. The issue however remained even after reinstalling ruby 3.3.0 and even with ruby master. Since this goes back to getaddrinfo (which is working without any issues outside of ruby) and there seems to be only one bigger change to stdlib socket, I'm assuming the problem was introduced with https://bugs.ruby-lang.org/issues/19965
```
3.3.0 :001 > require 'socket'
=> true
3.3.0 :002 > Socket.getaddrinfo('rubygems.org', 443)
(irb):2:in `getaddrinfo': getaddrinfo: Temporary failure in name resolution (Socket::ResolutionError)
from (irb):2:in `<main>'
from <internal:kernel>:187:in `loop'
from /usr/local/rvm/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0/gems/irb-1.11.0/exe/irb:9:in `<top (required)>'
from /usr/local/rvm/rubies/ruby-3.3.0/bin/irb:25:in `load'
from /usr/local/rvm/rubies/ruby-3.3.0/bin/irb:25:in `<main>'
3.3.0 :003 > Socket.getaddrinfo('rubygems.org', 443)
(irb):3:in `getaddrinfo': getaddrinfo: Temporary failure in name resolution (Socket::ResolutionError)
from (irb):3:in `<main>'
from <internal:kernel>:187:in `loop'
from /usr/local/rvm/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0/gems/irb-1.11.0/exe/irb:9:in `<top (required)>'
from /usr/local/rvm/rubies/ruby-3.3.0/bin/irb:25:in `load'
from /usr/local/rvm/rubies/ruby-3.3.0/bin/irb:25:in `<main>'
3.3.0 :004 > Socket.getaddrinfo('rubygems.org', 443)
=>
[["AF_INET", 443, "151.101.193.227", "151.101.193.227", 2, 1, 6],
["AF_INET", 443, "151.101.193.227", "151.101.193.227", 2, 2, 17],
["AF_INET", 443, "151.101.193.227", "151.101.193.227", 2, 3, 0],
...
["AF_INET6", 443, "2a04:4e42::483", "2a04:4e42::483", 10, 1, 6],
["AF_INET6", 443, "2a04:4e42::483", "2a04:4e42::483", 10, 2, 17],
["AF_INET6", 443, "2a04:4e42::483", "2a04:4e42::483", 10, 3, 0]]
3.3.0 :005 >
```
--
https://bugs.ruby-lang.org/
Issue #19461 has been reported by ioquatix (Samuel Williams).
----------------------------------------
Bug #19461: Time.local performance tanks in forked process (on macOS only?)
https://bugs.ruby-lang.org/issues/19461
* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
The following program demonstrates a performance regression in forked child processes when invoking `Time.local`:
```ruby
require 'benchmark'
require 'time'
def sir_local_alot
result = Benchmark.measure do
10_000.times do
tm = ::Time.local(2023)
end
end
$stderr.puts result
end
sir_local_alot
pid = fork do
sir_local_alot
end
Process.wait(pid)
```
On Linux the performance is similar, but on macOS, the performance is over 100x worse on my M1 laptop.
--
https://bugs.ruby-lang.org/
Issue #20233 has been reported by jmarrec (Julien Marrec).
----------------------------------------
Feature #20233: pkg-config not working on MSVC
https://bugs.ruby-lang.org/issues/20233
* Author: jmarrec (Julien Marrec)
* Status: Open
* Priority: Normal
----------------------------------------
The PKG_CONFIG variable is not respected in win32/Makefile.sub
Also, need to ideally use the `--msvc-syntax` flag (pkgconf 1.4.0, released 7 years ago, adds it).
But mostly, I realized that the `try_ldflags` in `lib/mkmf.rb` actually passes these ldflags as the `opt` parameter to the `link_command` function, and not as `ldflags`. While the UNIX systems are forgiving, the MSVC compiler is not, and because the flags are passed before the `-link`, MSVC complains that it ignores it and therefore cannot find the requested library.
--
https://bugs.ruby-lang.org/
Issue #20162 has been reported by peterzhu2118 (Peter Zhu).
----------------------------------------
Bug #20162: Memory leak when duplicating too complex object
https://bugs.ruby-lang.org/issues/20162
* Author: peterzhu2118 (Peter Zhu)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: DONTNEED, 3.2: REQUIRED, 3.3: REQUIRED
----------------------------------------
GitHub PR: https://github.com/ruby/ruby/pull/9449
Creating a ST table then calling st_replace leaks memory because the st_replace overwrites the ST table without freeing any of the existing memory. This commit changes it to use st_copy instead.
For example:
```ruby
RubyVM::Shape.exhaust_shapes
o = Object.new
o.instance_variable_set(:@a, 0)
10.times do
100_000.times { o.dup }
puts `ps -o rss= -p #{$$}`
end
```
Before:
```
23264
33600
42672
52160
61600
71728
81056
90528
100560
109840
```
After:
```
14752
14816
15584
15584
15664
15664
15664
15664
15664
15664
```
--
https://bugs.ruby-lang.org/
Issue #20188 has been reported by byroot (Jean Boussier).
----------------------------------------
Bug #20188: `Module#const_source_location` returns wrong information when real constant was defined but autoload is still ongoing
https://bugs.ruby-lang.org/issues/20188
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Ref: https://github.com/fxn/zeitwerk/issues/281
`const_source_location` keeps returning the location of the `autoload` call, even after the real constant was defined. It only starts returning the real constant location once the autoload was fully completed.
```ruby
# /tmp/autoload.rb
File.write("/tmp/const.rb", <<~RUBY)
module Const
LOCATION = Object.const_source_location(:Const)
end
RUBY
autoload :Const, "/tmp/const"
p Const::LOCATION
```
Expected Output:
```ruby
["/tmp/const.rb", 1]
```
Actual Output:
```ruby
["/tmp/autoload.rb", 8]
```
Potential patch: https://github.com/ruby/ruby/pull/9549
--
https://bugs.ruby-lang.org/