From e1655dad3a00a7b4026c653ff7c611811e7e34da Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 3 Feb 2026 16:13:24 +0900 Subject: [PATCH 01/17] Comment out to disable ppc64le and s390x CI builds They are cancelled after new permission. https://github.com/IBM/actionspz/issues/75 Other Ubuntu jobs unexpectedly terminated with their cancellation. --- .github/workflows/ubuntu.yml | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 2ed27e278b1dd4..0a4e19e229b9a0 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -177,30 +177,30 @@ jobs: SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot if: ${{ failure() }} - make-ibm: - strategy: - matrix: - include: - - test_task: check - os: ubuntu-24.04-ppc64le - - test_task: check - os: ubuntu-24.04-s390x - fail-fast: false - - env: *make-env - - runs-on: ${{ matrix.os }} - - if: >- - ${{github.repository == 'ruby/ruby' - && !(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') - )}} - - steps: *make-steps + # make-ibm: + # strategy: + # matrix: + # include: + # - test_task: check + # os: ubuntu-24.04-ppc64le + # - test_task: check + # os: ubuntu-24.04-s390x + # fail-fast: false + + # env: *make-env + + # runs-on: ${{ matrix.os }} + + # if: >- + # ${{github.repository == 'ruby/ruby' + # && !(false + # || contains(github.event.head_commit.message, '[DOC]') + # || contains(github.event.pull_request.title, '[DOC]') + # || contains(github.event.pull_request.labels.*.name, 'Documentation') + # || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + # )}} + + # steps: *make-steps # Separated from `make` job to avoid making it a required status check ruby-bench: From 066332465b927cf2d2b05d0d77014d7e3f48d933 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 2 Feb 2026 22:06:44 +0100 Subject: [PATCH 02/17] [ruby/json] Ensure `Generator::State` is kept on the stack Fix: https://github.com/ruby/json/issues/929 When calling `cState_partial_generate` from `mHash_to_json` or other `to_json` funcs, `VState` becomes unreachable very quickly, hence the compiler may optimize it out of the stack, and make it invisible to the GC stack scanning. This is particularly liekly given how aggressively we inline. Repro: ```ruby require 'json' test_data = { "flag" => true, "data" => 10000.times.map { [1.0] }, :flag => false, } 10.times do test_data.to_json end ``` But in practice the cause was just that the issued warning calls Hash#inspect on a big hash, which triggers GC. So it can be triggered even more reliably with: ```ruby require 'json' module JSON module Common def self.on_mixed_keys_hash(...) GC.start end end end test_data = { "flag" => true, "data" => 10000.times.map { [1.0] }, :flag => false, } test_data.to_json ``` https://github.com/ruby/json/commit/79b6e168ba --- ext/json/generator/generator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index dbba99c4558e63..ad9259864ea61f 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1540,7 +1540,9 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, .obj = obj, .func = func }; - return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data); + VALUE result = rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data); + RB_GC_GUARD(self); + return result; } /* call-seq: From 41238ccd85301b7d287a137d2fd8a94687f45784 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 2 Feb 2026 19:44:02 +0100 Subject: [PATCH 03/17] [ruby/json] fbuffer_append_str: assume string https://github.com/ruby/json/commit/fff25c9f4b --- ext/json/fbuffer/fbuffer.h | 14 ++++++++------ ext/json/generator/generator.c | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h index 752d153b31d5d5..8ce029a8c49dfd 100644 --- a/ext/json/fbuffer/fbuffer.h +++ b/ext/json/fbuffer/fbuffer.h @@ -161,23 +161,25 @@ static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr) static void fbuffer_append_str(FBuffer *fb, VALUE str) { - const char *newstr = StringValuePtr(str); - unsigned long len = RSTRING_LEN(str); + const char *ptr; + unsigned long len; + RSTRING_GETMEM(str, ptr, len); - fbuffer_append(fb, newstr, len); + fbuffer_append(fb, ptr, len); } static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat) { - const char *newstr = StringValuePtr(str); - unsigned long len = RSTRING_LEN(str); + const char *ptr; + unsigned long len; + RSTRING_GETMEM(str, ptr, len); fbuffer_inc_capa(fb, repeat * len); while (repeat) { #if JSON_DEBUG fb->requested = len; #endif - fbuffer_append_reserved(fb, newstr, len); + fbuffer_append_reserved(fb, ptr, len); repeat--; } } diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index ad9259864ea61f..3290de4015f9d9 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1374,7 +1374,7 @@ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *dat static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { VALUE tmp = rb_funcall(obj, i_to_s, 0); - fbuffer_append_str(buffer, tmp); + fbuffer_append_str(buffer, StringValue(tmp)); } #ifdef RUBY_INTEGER_UNIFICATION From 112c86e2640f596a4b7eeca6ebbe8c9909dfec08 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 3 Feb 2026 08:35:11 +0100 Subject: [PATCH 04/17] [ruby/json] Release 2.18.1 https://github.com/ruby/json/commit/6ec6e7baff --- ext/json/lib/json/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index 631beba83e91b6..95b88571005b7e 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module JSON - VERSION = '2.18.0' + VERSION = '2.18.1' end From 81a19adb1f27632c151519a22e51d28a42061f51 Mon Sep 17 00:00:00 2001 From: git Date: Tue, 3 Feb 2026 07:38:05 +0000 Subject: [PATCH 05/17] Update default gems list at 112c86e2640f596a4b7eeca6ebbe8c [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 4c9a3e8eaee538..4f35077bfe0ecf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -46,6 +46,7 @@ releases. * RubyGems 4.1.0.dev * bundler 4.1.0.dev +* json 2.18.1 * prism 1.9.0 * resolv 0.7.1 * stringio 3.2.1.dev From c0eca60eba638aa6bcb91f1b7d1467d697eec81d Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 3 Feb 2026 08:39:10 +0100 Subject: [PATCH 06/17] [ruby/json] Remove codepaths under !RUBY_INTEGER_UNIFICATION This was for pre Ruby 2.4 support which we dropped a while ago. https://github.com/ruby/json/commit/b11ce01ca6 --- ext/json/generator/generator.c | 38 ---------------------------------- 1 file changed, 38 deletions(-) diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 3290de4015f9d9..186a45714d48eb 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -74,9 +74,7 @@ static void generate_json_string(FBuffer *buffer, struct generate_json_data *dat static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj); static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj); static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj); -#ifdef RUBY_INTEGER_UNIFICATION static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj); -#endif static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj); static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj); static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj); @@ -815,7 +813,6 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) return cState_partial_generate(Vstate, self, generate_json_array, Qfalse); } -#ifdef RUBY_INTEGER_UNIFICATION /* * call-seq: to_json(*) * @@ -828,32 +825,6 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self) return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse); } -#else -/* - * call-seq: to_json(*) - * - * Returns a JSON string representation for this Integer number. - */ -static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self) -{ - rb_check_arity(argc, 0, 1); - VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); - return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse); -} - -/* - * call-seq: to_json(*) - * - * Returns a JSON string representation for this Integer number. - */ -static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self) -{ - rb_check_arity(argc, 0, 1); - VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); - return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse); -} -#endif - /* * call-seq: to_json(*) * @@ -1377,7 +1348,6 @@ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *dat fbuffer_append_str(buffer, StringValue(tmp)); } -#ifdef RUBY_INTEGER_UNIFICATION static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { if (FIXNUM_P(obj)) @@ -1385,7 +1355,6 @@ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *da else generate_json_bignum(buffer, data, obj); } -#endif static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { @@ -2165,16 +2134,9 @@ void Init_generator(void) VALUE mArray = rb_define_module_under(mGeneratorMethods, "Array"); rb_define_method(mArray, "to_json", mArray_to_json, -1); -#ifdef RUBY_INTEGER_UNIFICATION VALUE mInteger = rb_define_module_under(mGeneratorMethods, "Integer"); rb_define_method(mInteger, "to_json", mInteger_to_json, -1); -#else - VALUE mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum"); - rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1); - VALUE mBignum = rb_define_module_under(mGeneratorMethods, "Bignum"); - rb_define_method(mBignum, "to_json", mBignum_to_json, -1); -#endif VALUE mFloat = rb_define_module_under(mGeneratorMethods, "Float"); rb_define_method(mFloat, "to_json", mFloat_to_json, -1); From 3820b354f1cbfbdeb60818a96de7b25995c5c1ac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 06:46:53 +0000 Subject: [PATCH 07/17] =?UTF-8?q?Fix=20typo:=20wich=20=E2=86=92=20which=20?= =?UTF-8?q?in=20ractor.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hsbt <12301+hsbt@users.noreply.github.com> --- doc/language/ractor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/language/ractor.md b/doc/language/ractor.md index 72fbde6e5a083d..a0acaf3a918e1a 100644 --- a/doc/language/ractor.md +++ b/doc/language/ractor.md @@ -12,7 +12,7 @@ You can create multiple Ractors which can run ruby code in parallel with each ot * Ruby processes start with one ractor (called the *main ractor*). * If the main ractor terminates, all other ractors receive termination requests, similar to how threads behave. * Each Ractor contains one or more `Thread`s. - * Threads within the same ractor share a ractor-wide global lock (GVL in MRI terminology), so they can't run in parallel wich each other (without releasing the GVL explicitly in C extensions). Threads in different ractors can run in parallel. + * Threads within the same ractor share a ractor-wide global lock (GVL in MRI terminology), so they can't run in parallel with each other (without releasing the GVL explicitly in C extensions). Threads in different ractors can run in parallel. * The overhead of creating a ractor is slightly above the overhead of creating a thread. ### Limited sharing between Ractors From 2f8ab8e4703936f650d8dfc0ef69c174b6062761 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 14:54:51 +0900 Subject: [PATCH 08/17] filter TracePoint :line events by file in target_thread test to avoid such failure: ``` 1) Failure: TestSetTraceFunc#test_enable_target_thread [/tmp/ruby/src/trunk/test/ruby/test_settracefunc.rb:2595]: <[#, #, #]> expected but was <[#, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #, #]>. ``` --- test/ruby/test_settracefunc.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index d3b2441e21e7c3..8b0e08fc97d2a7 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -2583,6 +2583,7 @@ def test_script_compiled def test_enable_target_thread events = [] TracePoint.new(:line) do |tp| + next unless tp.path == __FILE__ events << Thread.current end.enable(target_thread: Thread.current) do _a = 1 @@ -2596,6 +2597,7 @@ def test_enable_target_thread events = [] tp = TracePoint.new(:line) do |tp| + next unless tp.path == __FILE__ events << Thread.current end From 25422c0d0733f50367c5533c7c4b326426848528 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 15:11:47 +0900 Subject: [PATCH 09/17] use SIGSEGV on ractor timeout to show C level backtrace for the following failure: ``` 1) Error: TestObjSpaceRactor#test_undefine_finalizer: Test::Unit::ProxyError: execution of Test::Unit::CoreAssertions#assert_separately expired timeout (10 sec) pid 861177 killed by SIGTERM (signal 15) | /tmp/ruby/src/trunk-yjit/test/objspace/test_ractor.rb:17:in 'TestObjSpaceRactor#test_undefine_finalizer' ``` --- test/objspace/test_ractor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/objspace/test_ractor.rb b/test/objspace/test_ractor.rb index 996d83fbd214dd..0fe4c32f2f0741 100644 --- a/test/objspace/test_ractor.rb +++ b/test/objspace/test_ractor.rb @@ -14,7 +14,7 @@ def test_tracing_does_not_crash end def test_undefine_finalizer - assert_ractor(<<~'RUBY', require: 'objspace') + assert_ractor(<<~'RUBY', require: 'objspace', signal: :SEGV) def fin ->(id) { } end From 07a0b68a85be84fa11ad63e60faeec4e4fd02490 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 15:02:16 +0900 Subject: [PATCH 10/17] apply timeout scale in wait_exception to avoid such case: ``` 1) Failure: TestProcess#test_wait_exception [/tmp/ruby/src/trunk-asserts-nopara/test/ruby/test_process.rb:1588]: [ruby-dev:49176] [Bug #11340]: 3.696015712 seconds to interrupt Process.wait. Expected 3.696015712 to be < 3. ``` --- test/ruby/test_process.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index b3a88b664cc09d..56a3c3d18f7156 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -1568,7 +1568,7 @@ def test_waitall def test_wait_exception bug11340 = '[ruby-dev:49176] [Bug #11340]' t0 = t1 = nil - sec = 3 + sec = EnvUtil.apply_timeout_scale(3) code = "puts;STDOUT.flush;Thread.start{gets;exit};sleep(#{sec})" IO.popen([RUBY, '-e', code], 'r+') do |f| pid = f.pid From 8cb3663a54587fcb62242af11e0d96cccdf3ffed Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 15:27:03 +0900 Subject: [PATCH 11/17] Try to send SEGV to show C bt for the following failure ``` 1) Error: TestClass#test_safe_multi_ractor_subclasses_list_mutation: Test::Unit::ProxyError: execution of Test::Unit::CoreAssertions#assert_separately expired timeout (10 sec) pid 814469 killed by SIGTERM (signal 15) | /tmp/ruby/src/trunk_gcc14/test/ruby/test_class.rb:922:in 'TestClass#test_safe_multi_ractor_subclasses_list_mutation' ``` --- test/ruby/test_class.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb index 8f12e06685bb1f..cc2e1ab2324e33 100644 --- a/test/ruby/test_class.rb +++ b/test/ruby/test_class.rb @@ -919,7 +919,7 @@ class T end def test_safe_multi_ractor_subclasses_list_mutation - assert_ractor "#{<<~"begin;"}\n#{<<~'end;'}" + assert_ractor "#{<<~"begin;"}\n#{<<~'end;'}", signal: :SEGV begin; 4.times.map do Ractor.new do From 2a57e636ae79711d7b4b2dd8fd754fa98629ce49 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 15:17:03 +0900 Subject: [PATCH 12/17] try to extend timeout for repeated refine test for the following failure: ``` 1) Error: TestRefinement#test_refining_module_repeatedly: Test::Unit::ProxyError: execution of Test::Unit::CoreAssertions#assert_in_out_err expired timeout (10 sec) pid 56455 exit 0 | ok | /Users/runner/work/ruby/ruby/src/test/ruby/test_refinement.rb:2258:in 'TestRefinement#test_refining_module_repeatedly' ``` --- test/ruby/test_refinement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 209e55294b1889..f4fe2fc44b5b61 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -2255,7 +2255,7 @@ def foo def test_refining_module_repeatedly bug14070 = '[ruby-core:83617] [Bug #14070]' - assert_in_out_err([], <<-INPUT, ["ok"], [], bug14070) + assert_in_out_err([], <<-INPUT, ["ok"], [], bug14070, timeout: 30) 1000.times do Class.new do include Enumerable From f045a820edcf3a198c03b4eaa9a849418e31d469 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 17:09:56 +0900 Subject: [PATCH 13/17] try to extend timeout for the following failure: ``` 1) Timeout: TestResolvDNS#test_multiple_servers_with_timeout_and_truncated_tcp_fallback ``` --- test/resolv/test_dns.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb index 7a01909eeb9a4b..69a0e03ec9c716 100644 --- a/test/resolv/test_dns.rb +++ b/test/resolv/test_dns.rb @@ -721,13 +721,14 @@ def test_multiple_servers_with_timeout_and_truncated_tcp_fallback client_thread = Thread.new do Resolv::DNS.open(nameserver_port: [[server1_address, server1_port], [server2_address, server2_port]]) do |dns| - dns.timeouts = [0.1, 0.2] + dns.timeouts = [EnvUtil.apply_timeout_scale(0.1), + EnvUtil.apply_timeout_scale(0.2)] dns.getresources('foo.example.org', Resolv::DNS::Resource::IN::A) end end udp_server1_thread = Thread.new do - msg, (_, client_port, _, client_address) = Timeout.timeout(5) { u1.recvfrom(4096) } + msg, (_, client_port, _, client_address) = Timeout.timeout(EnvUtil.apply_timeout_scale(5)) { u1.recvfrom(4096) } id, word2, _qdcount, _ancount, _nscount, _arcount = msg.unpack('nnnnnn') opcode = (word2 & 0x7800) >> 11 rd = (word2 & 0x0100) >> 8 From 5ebccee59dc327ffb9e46a53cbe2ff853247fcd6 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 3 Feb 2026 16:49:04 +0900 Subject: [PATCH 14/17] check zeros raise when assert_linear_performance measures only zeros to check the following error: ``` 1) Error: TestRegexp#test_linear_performance: Test::Unit::ProxyError: nil can't be coerced into Integer /home/opc/ruby/src/master/test/ruby/test_regexp.rb:2301:in 'TestRegexp#test_linear_performance' ``` --- tool/lib/core_assertions.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb index e29a0e3c25a0e3..5ca318a5989753 100644 --- a/tool/lib/core_assertions.rb +++ b/tool/lib/core_assertions.rb @@ -911,10 +911,11 @@ def assert_linear_performance(seq, rehearsal: nil, pre: ->(n) {n}) first = seq.first *arg = pre.call(first) - times = (0..(rehearsal || (2 * first))).map do + raw_times = (0..(rehearsal || (2 * first))).map do measure[arg, "rehearsal"].nonzero? end - times.compact! + times = raw_times.compact + raise "all measurements are zero: #{raw_times.inspect}" if times.empty? tmin, tmax = times.minmax # safe_factor * tmax * rehearsal_time_variance_factor(equals to 1 when variance is small) From f1201bcf1b6ff073f89e84bafe5040a5712dbbf5 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 3 Feb 2026 17:27:47 +0900 Subject: [PATCH 15/17] [ruby/rubygems] Update vendored resolv to 0.7.0 https://github.com/ruby/rubygems/commit/844a05543b --- lib/rubygems/vendor/resolv/lib/resolv.rb | 44 ++++++++++++++++-------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/rubygems/vendor/resolv/lib/resolv.rb b/lib/rubygems/vendor/resolv/lib/resolv.rb index 168df21f3ece42..4f48e0642bf48a 100644 --- a/lib/rubygems/vendor/resolv/lib/resolv.rb +++ b/lib/rubygems/vendor/resolv/lib/resolv.rb @@ -4,6 +4,7 @@ require_relative '../../../vendored_timeout' require 'io/wait' require_relative '../../../vendored_securerandom' +require 'rbconfig' # Gem::Resolv is a thread-aware DNS resolver library written in Ruby. Gem::Resolv can # handle multiple DNS requests concurrently without blocking the entire Ruby @@ -33,7 +34,8 @@ class Gem::Resolv - VERSION = "0.6.2" + # The version string + VERSION = "0.7.0" ## # Looks up the first IP address for +name+. @@ -173,21 +175,19 @@ class ResolvError < StandardError; end class ResolvTimeout < Gem::Timeout::Error; end - WINDOWS = /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/ - private_constant :WINDOWS - ## # Gem::Resolv::Hosts is a hostname resolver that uses the system hosts file. class Hosts - if WINDOWS + if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/ begin require 'win32/resolv' unless defined?(Win32::Resolv) - DefaultFileName = Win32::Resolv.get_hosts_path || IO::NULL + hosts = Win32::Resolv.get_hosts_path || IO::NULL rescue LoadError end end - DefaultFileName ||= '/etc/hosts' + # The default file name for host names + DefaultFileName = hosts || '/etc/hosts' ## # Creates a new Gem::Resolv::Hosts, using +filename+ for its data source. @@ -525,6 +525,8 @@ def each_resource(name, typeclass, &proc) } end + # :stopdoc: + def fetch_resource(name, typeclass) lazy_initialize truncated = {} @@ -1021,8 +1023,7 @@ def Config.parse_resolv_conf(filename) def Config.default_config_hash(filename="/etc/resolv.conf") if File.exist? filename Config.parse_resolv_conf(filename) - elsif WINDOWS - require 'win32/resolv' unless defined?(Win32::Resolv) + elsif defined?(Win32::Resolv) search, nameserver = Win32::Resolv.get_resolv_info config_hash = {} config_hash[:nameserver] = nameserver if nameserver @@ -2926,15 +2927,21 @@ class HTTPS < ServiceBinding class IPv4 - ## - # Regular expression IPv4 addresses must match. - Regex256 = /0 |1(?:[0-9][0-9]?)? |2(?:[0-4][0-9]?|5[0-5]?|[6-9])? - |[3-9][0-9]?/x + |[3-9][0-9]?/x # :nodoc: + + ## + # Regular expression IPv4 addresses must match. Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/ + ## + # Creates a new IPv4 address from +arg+ which may be: + # + # IPv4:: returns +arg+. + # String:: +arg+ must match the IPv4::Regex constant + def self.create(arg) case arg when IPv4 @@ -3243,13 +3250,15 @@ def make_udp_requester # :nodoc: end - module LOC + module LOC # :nodoc: ## # A Gem::Resolv::LOC::Size class Size + # Regular expression LOC size must match. + Regex = /^(\d+\.*\d*)[m]$/ ## @@ -3275,6 +3284,7 @@ def self.create(arg) end end + # Internal use; use self.create. def initialize(scalar) @scalar = scalar end @@ -3312,6 +3322,8 @@ def hash # :nodoc: class Coord + # Regular expression LOC Coord must match. + Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/ ## @@ -3341,6 +3353,7 @@ def self.create(arg) end end + # Internal use; use self.create. def initialize(coordinates,orientation) unless coordinates.kind_of?(String) raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}") @@ -3403,6 +3416,8 @@ def hash # :nodoc: class Alt + # Regular expression LOC Alt must match. + Regex = /^([+-]*\d+\.*\d*)[m]$/ ## @@ -3428,6 +3443,7 @@ def self.create(arg) end end + # Internal use; use self.create. def initialize(altitude) @altitude = altitude end From cf22fe7f0857f0c980d9966047579b65c7798126 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 3 Feb 2026 19:28:42 +0900 Subject: [PATCH 16/17] Lock to install uutils-coreutils@0.5.0 --- .github/workflows/windows.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index f9d1335d464016..ce4221137d601e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -83,7 +83,8 @@ jobs: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser iwr -useb get.scoop.sh | iex Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH - scoop install vcpkg uutils-coreutils + scoop install vcpkg + scoop install uutils-coreutils@0.5.0 shell: pwsh - name: Restore vcpkg artifact From 4bf1cb087bc8ff065b6226037329d7464fa3e96c Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:10:01 +0100 Subject: [PATCH 17/17] [ruby/prism] Better guard against syntax invalid code in ripper lex translator Closes https://github.com/ruby/prism/pull/3899 Also better compatibility by only dropping the last token if it is actually EOF https://github.com/ruby/prism/commit/128ab52be9 --- lib/prism/lex_compat.rb | 9 +++++---- test/prism/ruby/ripper_test.rb | 11 +++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 4c516a9de0acb9..5b685716cc5569 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -758,8 +758,9 @@ def result end end - # Drop the EOF token from the list - tokens = tokens[0...-1] + # Drop the EOF token from the list. The EOF token may not be + # present if the source was syntax invalid + tokens = tokens[0...-1] if tokens.dig(-1, 1) == :on_eof # We sort by location because Ripper.lex sorts. tokens.sort_by! do |token| @@ -804,7 +805,7 @@ def insert_on_sp(tokens, source, data_loc, bom, eof_token) next_whitespace_index += 1 first_whitespace = sp_value[0...continuation_index] continuation = sp_value[continuation_index...next_whitespace_index] - second_whitespace = sp_value[next_whitespace_index..] + second_whitespace = sp_value[next_whitespace_index..] || "" new_tokens << [[sp_line, sp_column], :on_sp, first_whitespace, prev_token_state] unless first_whitespace.empty? new_tokens << [[sp_line, sp_column + continuation_index], :on_sp, continuation, prev_token_state] @@ -819,7 +820,7 @@ def insert_on_sp(tokens, source, data_loc, bom, eof_token) prev_token_end = start_offset + token[2].bytesize end - unless data_loc # no trailing :on_sp with __END__ as it is always preceded by :on_nl + if !data_loc && eof_token # no trailing :on_sp with __END__ as it is always preceded by :on_nl end_offset = eof_token.location.end_offset if prev_token_end < end_offset new_tokens << [ diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 52a5ad7ef4e2f9..758505ac2ab96d 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -140,6 +140,17 @@ def test_lexer assert_raise(SyntaxError) { Translation::Ripper::Lexer.new("1 +").lex(raise_errors: true) } end + + # On syntax invalid code the output doesn't always match up + # In these cases we just want to make sure that it doesn't raise. + def test_lex_invalid_syntax + assert_nothing_raised do + Translation::Ripper.lex('scan/\p{alpha}/') + end + + assert_equal(Ripper.lex('if;)'), Translation::Ripper.lex('if;)')) + end + def test_tokenize source = "foo;1;BAZ" assert_equal(Ripper.tokenize(source), Translation::Ripper.tokenize(source))