[pull] master from ruby:master - #1352
Merged
Merged
Conversation
box_entry_free could run before other T_DATA objects are finalized in rb_objspace_call_finalizer, and FreeLibrary there unmapped the rb_data_type_t and dfree functions that later finalization still dereferences, crashing any boxed process that leaves extension objects alive at exit. Keep the copied DLLs loaded until ruby_vm_destruct, then unload and delete them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This reverts commit 86817cf.
A label longer than 255 octets wrapped its length octet mod 256 while the data was written unchanged, so the wire bytes decoded to a different name than the caller asked for. A hostname that passed an application's allowlist could be sent as a query for an unrelated domain. The 63 octet limit goes on the label path. put_string also writes character-strings, which may legitimately be 255 octets, so it keeps the wider limit that its single length octet can represent. ruby/resolv@137df11fc0 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The counter started at -1, which measures the presentation form, so a name encoding to 257 octets passed the 255 octet limit of RFC 1035 section 3.1. The encoded form includes each label's length octet and the root label's terminating zero octet. ruby/resolv@0a5ef9b498 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A hostname is runtime data rather than a programming mistake, and callers already wrap name resolution in rescue Resolv::ResolvError. Rejecting an oversized name with ArgumentError escaped that rescue, since Config#generate_candidates runs outside Config#resolv's own handler. No new exception class: resolv raises ResolvError directly in nine other places and subclasses it only where a caller has to tell cases apart. ruby/resolv@346416498a Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Checking in Name.create left two ways to build an over-long label: Name.new, which Config#generate_candidates uses to append search domains, and the search list itself, which Config splits without going through Name.create. Label::Str is the one place every label is built, so enforcing it there covers both, and the encoder guard becomes a backstop rather than the only line of defence. Callers keep the error their own contract promises. Name.create still reports ResolvError, and get_label reports DecodeError, which also means a length octet in the reserved 64..191 range is no longer read as a label. ruby/resolv@07f3b7d098 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s it The comment predates the check moving into Label::Str and read as though a label of 64 octets already overflowed its length octet. It does not: 64 to 255 write a reserved or compression pointer value, and only 256 or more wrap. Say which is which, and say that this guard now only catches a raw string passed straight to put_labels. Both messages also name the limit they enforce, as the other size checks do. ruby/resolv@972ec472e3 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… and SvcParamKeys Decoding a response with unknown (type, class) pairs or unknown SvcParamKeys generated an anonymous class per value and registered it in a constant and in ClassHash permanently, so a spoofed or malicious response carrying many unknown values could exhaust memory even after the response was discarded and GC ran (a denial of service). Generate the classes on demand without registering them so they stay collectable; the default RR and SvcParam classes are still registered at require time. ruby/resolv@fa5e689c46 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ruby/resolv@95e0a6664c Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dropping the class cache made every decode build a fresh class for an unknown type, so comparing the classes by identity reported two otherwise identical resources, questions, and messages as different. ruby/resolv@05185b4322 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e zipped array Generic#== accepted only direct subclasses while Message compared any descendant, so an instance of a subclass of a generated class compared unequal. Both now go through Generic.type_class_equal?. Passing a block to zip also avoids allocating the paired array and stops at the first mismatch. ruby/resolv@fcff0a19e4 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Block param minimization was introduced here #17311, but a few tests did not properly eliminate redundant block params. This is because I used `Vec::resize`. For most passes this was fine, especially when trivial block params were discovered. However, in the case where the number of params is not reduced, the vec is not properly cleared between analyses. In some cases, this leaves a dangling trivial param that can be changed if _other_ blocks remove trivial params. In addition to resize, we use `Vec::truncate` which fixes the problem. This test also requires the removal of a test that has issues due to pass ordering. Unless we develop a mechanism to run single analysis passes in tests, we may run into more such issues.
We shouldn't record JIT information before the JIT is actually enabled.
This change doesn't seem to affect ZJIT or YJIT performance beyond the
margin of error:
ZJIT:
-------------- ------------ ------------ -------------- -------------
bench master (ms) branch (ms) branch 1st itr master/branch
activerecord 50.1 ± 7.4% 49.0 ± 5.7% 0.948 1.022
chunky-png 164.2 ± 2.1% 166.8 ± 2.8% 0.985 0.985
erubi-rails 247.0 ± 2.8% 264.6 ± 2.2% 0.945 0.934
hexapdf 571.3 ± 1.0% 565.4 ± 1.2% 0.959 1.010
liquid-c 17.6 ± 13.1% 19.2 ± 12.9% 0.976 0.920
liquid-compile 15.7 ± 11.0% 15.6 ± 7.5% 0.978 1.003
liquid-il 79.8 ± 2.0% 78.2 ± 2.2% 0.993 1.021
liquid-render 32.3 ± 6.8% 32.3 ± 6.3% 1.001 0.999
lobsters 243.8 ± 4.9% 242.8 ± 4.7% 0.976 1.004
mail 38.8 ± 3.1% 39.5 ± 5.1% 0.993 0.982
psych-load 612.4 ± 1.5% 610.0 ± 1.9% 1.001 1.004
railsbench 343.8 ± 2.9% 350.8 ± 2.2% 0.991 0.980
rubocop 50.0 ± 10.6% 51.2 ± 12.0% 1.019 0.978
ruby-lsp 42.9 ± 3.8% 43.2 ± 3.7% 0.974 0.993
sequel 18.5 ± 6.6% 18.7 ± 6.6% 1.021 0.991
shipit 344.3 ± 1.3% 339.8 ± 3.4% 0.981 1.013
-------------- ------------ ------------ -------------- -------------
YJIT:
-------------- ------------ ------------ -------------- -------------
bench master (ms) branch (ms) branch 1st itr master/branch
activerecord 42.6 ± 7.7% 40.6 ± 5.5% 1.099 1.048
chunky-png 164.7 ± 1.3% 164.8 ± 1.1% 1.060 0.999
erubi-rails 256.7 ± 3.3% 241.3 ± 2.3% 1.035 1.064
hexapdf 445.6 ± 1.0% 444.6 ± 1.0% 1.012 1.002
liquid-c 16.4 ± 11.2% 16.7 ± 13.3% 1.037 0.986
liquid-compile 14.5 ± 11.5% 14.3 ± 7.8% 0.990 1.011
liquid-il 74.9 ± 2.6% 73.4 ± 3.6% 0.993 1.021
liquid-render 23.1 ± 8.9% 23.3 ± 8.7% 1.001 0.992
lobsters 239.9 ± 9.9% 238.7 ± 9.3% 0.989 1.005
mail 29.2 ± 4.6% 30.0 ± 5.8% 0.977 0.973
psych-load 515.5 ± 1.2% 511.5 ± 0.7% 0.973 1.008
railsbench 317.4 ± 2.2% 317.9 ± 2.5% 1.008 0.998
rubocop 42.1 ± 18.5% 42.0 ± 14.4% 1.052 1.004
ruby-lsp 41.5 ± 3.8% 41.6 ± 3.8% 1.013 0.998
sequel 18.5 ± 6.6% 18.2 ± 5.4% 1.150 1.018
shipit 282.8 ± 3.8% 285.5 ± 5.2% 1.000 0.991
-------------- ------------ ------------ -------------- -------------
Bumps the github-actions group with 1 update in the / directory: [taiki-e/install-action](https://github.com/taiki-e/install-action). Updates `taiki-e/install-action` from 2.86.6 to 2.86.7 - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@6cd1350...b6ff580) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.86.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com>
… flag Every documented spelling of the flag raises before reaching it, so the only way in was Thor resolving `--skip-no-prune` to a negated value, which `flag_passed?` does not match. That let an undocumented spelling change a setting the documented one is refused for. ruby/rubygems@197eccbeed Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The `prune` vocabulary is being reused for a new setting, and `no_prune` was already a poor name for a flag that only decides whether `bundle cache` keeps gems that dropped out of the resolution. `no_prune` is still read until Bundler 5 removes it, resolved one priority level at a time so that an old name set locally keeps beating a current name set globally, the way the documented order promises. ruby/rubygems@98eaec7e9e Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
In the following code,
```ruby
def test(cond)
if cond
x = 1
else
x = 1
end
x
end
```
the `x` after the conditional would ordinarily get a block param merging two constant `1`. Even if we had dominator-based GVN, this would still happen; each `1` is in a sibling block (they would need to be hoisted).
This also happens a lot with nil-filled locals; interpreter and JIT entry blocks nil-fill the FrameState for each local variable and these nils get passed around when they don't need to.
Instead of doing that, determine if we know the value of a parameter even if it has multiple input SSA values; joining two `nil` will always produce a `nil`, for eaxmple.
This speeds up some local-heavy benchmarks such as protoboeuf.
Before:
```
plum% WARMUP_ITRS=0 MIN_BENCH_ITRS=10 MIN_BENCH_TIME=0 ruby --zjit benchmarks/protoboeuf/benchmark.rb
ruby 4.1.0dev (2026-08-18T13:12:35Z master 6b719ac) +ZJIT stats +PRISM [arm64-darwin25]
itr: time
#1: 96ms
#2: 22ms
#3: 33ms
#4: 21ms
#5: 19ms
#6: 20ms
#7: 19ms
#8: 19ms
#9: 20ms
#10: 20ms
```
After:
```
plum% WARMUP_ITRS=0 MIN_BENCH_ITRS=10 MIN_BENCH_TIME=0 ruby --zjit benchmarks/protoboeuf/benchmark.rb
ruby 4.1.0dev (2026-08-18T15:51:16Z mb-remove-constant.. 2fbcac7) +ZJIT stats +PRISM [arm64-darwin25]
itr: time
#1: 81ms
#2: 16ms
#3: 26ms
#4: 15ms
#5: 14ms
#6: 14ms
#7: 14ms
#8: 14ms
#9: 14ms
#10: 14ms
```
…ication `Bundler.load_gemspec_uncached` returns nil when the gemspec evaluates to nil, which an empty file does. `CLI::Init` was the only caller not guarding against that, so it crashed with a `NoMethodError` backtrace after already writing a partial Gemfile. ruby/rubygems@fc20938c4f Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
In iseq_scan_bits, we only update original_iseq if the element at code moved. However, this isn't correct as it's possible that code has already gotten updated but not original_iseq. This will cause original_iseq to not get updated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )