Skip to content

Commit 0ac30d1

Browse files
committed
[GR-54907] Backport changes in TruffleRuby master branch to the 24.1 release branch. Part 2
PullRequest: truffleruby/4336
2 parents 6e2007e + b289d93 commit 0ac30d1

File tree

181 files changed

+2239
-981
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+2239
-981
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Bug fixes:
1717
* Repair `IO#{wait_readable,wait_writable,wait}` to be interruptible (#3504, @andrykonchin).
1818
* Fix Hash value omission for constant names (@andrykonchin).
1919
* Fix `MatchData#[index, length]` when index is larger than number of matched values (@andrykonchin).
20+
* Fix `#each` for a foreign iterator which is also iterable (#3630, @eregon).
2021

2122
Compatibility:
2223

@@ -33,11 +34,23 @@ Compatibility:
3334
* Fix `Enumerable#reduce` to handle non-Symbol method name parameter (#2931, @andrykonchin).
3435
* Fix `RangeError` message to match CRuby for `Integer#chr` called with invalid codepoint argument (#2795, @andrykonchin).
3536
* Joni has been updated from 2.1.44 to 2.2.1 (@andrykonchin).
37+
* Fix `Hash#to_h` called with a block and pass key and value to the block as separate arguments (#3607, @andrykonchin).
38+
* Fix `StringIO#initialize` and preserve initial string's encoding when mode is `w` so the initial string is truncated (#3599, @andrykonchin).
39+
* Fix `IO#{autoclose=,autoclose?}` and raise `IOError` when io is closed (@andrykonchin).
40+
* Fix `Thread#{thread_variable_get,thread_variable_set,thread_variable?,key?,[],[]=,fetch}` and convert a non-String/Symbol thread-local variable name to String using `#to_str` (@andrykonchin).
41+
* Fix formatting in `Exception#full_message` when `RuntimeError` is not handled and `highlight` option is specified (@andrykonchin).
42+
* Fix `String#encode` and convert fallback values into String using `#to_str` (@andrykonchin).
43+
* Fix `Kernel.warn` and don't call `Warning#warn` if a specified category is disabled (@andrykonchin).
44+
* Fix `$!` global variable and make it fiber-local (@andrykonchin).
45+
* Fix `rb_set_errinfo` and `rb_errinfo` and store an error separately from `$!` (#2890, @andrykonchin).
46+
* Fix `rb_mutex_synchronize` to not wrap/unwrap result value (#3624, @andrykonchin).
47+
* Add `StringIO#set_encoding_by_bom` method (#3632, @andrykonchin).
3648

3749
Performance:
3850

3951
* Fix inline caching for Regexp creation from Strings (#3492, @andrykonchin, @eregon).
4052
* Optimize `Integer#pow` method for small modulus values (#3544, @andrykonchin).
53+
* Avoid repeated copies from native to managed string when matching Regexps on a native string (#2193, @eregon).
4154

4255
Changes:
4356

ci.jsonnet

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,8 @@ local composition_environment = utils.add_inclusion_tracking(part_definitions, "
633633
"ruby-benchmarks-asciidoctor-svm-ce": shared + asciidoctor + svm_configurations["svm-ce"],
634634
"ruby-benchmarks-asciidoctor-svm-ee": shared + asciidoctor + svm_configurations["svm-ee"],
635635

636-
local warmup = $.benchmark.runner + $.benchmark.warmup + { timelimit: "01:05:00" },
637-
"ruby-benchmarks-warmup-mri": shared + warmup + other_rubies.mri + { timelimit: "01:20:00" },
636+
local warmup = $.benchmark.runner + $.benchmark.warmup + { timelimit: "01:15:00" },
637+
"ruby-benchmarks-warmup-mri": shared + warmup + other_rubies.mri + { timelimit: "01:30:00" },
638638
"ruby-benchmarks-warmup-jruby": shared + warmup + other_rubies.jruby,
639639
"ruby-benchmarks-warmup-jvm-ce": shared + warmup + graal_configurations["jvm-ce"] + $.use.no_multi_tier,
640640
"ruby-benchmarks-warmup-jvm-ce-3threads": shared + warmup + graal_configurations["jvm-ce"] + $.use.no_multi_tier + $.use.three_threads,

common.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Jsonnet files should not include this file directly but use ci/common.jsonnet instead."
55
],
66

7-
"mx_version": "7.25.5",
7+
"mx_version": "7.27.5",
88

99
"COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet",
1010
"jdks": {
@@ -45,13 +45,13 @@
4545
"labsjdk-ee-21-llvm": {"name": "labsjdk", "version": "ee-21.0.2+13-jvmci-23.1-b33-sulong", "platformspecific": true },
4646
"graalvm-ee-21": {"name": "graalvm-java21", "version": "23.1.3", "platformspecific": true },
4747

48-
"oraclejdk-latest": {"name": "jpg-jdk", "version": "23", "build_id": "jdk-23+26", "platformspecific": true, "extrabundles": ["static-libs"]},
49-
"labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-23+26-jvmci-b01", "platformspecific": true },
50-
"labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-23+26-jvmci-b01-debug", "platformspecific": true },
51-
"labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-23+26-jvmci-b01-sulong", "platformspecific": true },
52-
"labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-23+26-jvmci-b01", "platformspecific": true },
53-
"labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-23+26-jvmci-b01-debug", "platformspecific": true },
54-
"labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-23+26-jvmci-b01-sulong", "platformspecific": true }
48+
"oraclejdk-latest": {"name": "jpg-jdk", "version": "23", "build_id": "jdk-23+32", "platformspecific": true, "extrabundles": ["static-libs"]},
49+
"labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-23+32-jvmci-b01", "platformspecific": true },
50+
"labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-23+32-jvmci-b01-debug", "platformspecific": true },
51+
"labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-23+32-jvmci-b01-sulong", "platformspecific": true },
52+
"labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-23+32-jvmci-b01", "platformspecific": true },
53+
"labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-23+32-jvmci-b01-debug", "platformspecific": true },
54+
"labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-23+32-jvmci-b01-sulong", "platformspecific": true }
5555
},
5656

5757
"eclipse": {

doc/contributor/cexts.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,10 @@ natively.
4646

4747
### Compilation
4848

49-
We compile C extensions using the standard `mkmf` tool, and `clang` compilers
50-
which have flags set to generate bitcode alongside machine code.
49+
We compile C extensions using the standard `mkmf` tool, and `gcc`/`clang` compilers.
5150

5251
We pipe C source code through a pre-processor `lib/cext/preprocess.rb` before it
53-
goes to `clang` to workaround some limitations.
52+
goes to `gcc`/`clang` to work around some limitations.
5453

5554
### API functions
5655

doc/user/known-cves.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Cross-reference with the details on [the MRI website](https://www.ruby-lang.org/
1919

2020
Number | Description | Their Mitigation | Test | Our Mitigation
2121
--- | --- | --- | --- | ---
22+
CVE-2024-39908 | DoS in REXML | [Fix](https://github.com/ruby/rexml/compare/v3.3.1...v3.3.2) | [Test](https://github.com/ruby/rexml/compare/v3.3.1...v3.3.2) | [same mitigation as CRuby](https://www.ruby-lang.org/en/news/2024/07/16/dos-rexml-cve-2024-39908/), users must update rexml to 3.3.2+ if they use it
2223
CVE-2024-35176 | DoS in REXML | [Fix](https://github.com/ruby/rexml/pull/126/commits/ba70cfefadf7e79885fe08228d1df4c0549ad0f8) | [Test](https://github.com/ruby/rexml/pull/126/commits/ba70cfefadf7e79885fe08228d1df4c0549ad0f8) | [same mitigation as CRuby](https://www.ruby-lang.org/en/news/2024/05/16/dos-rexml-cve-2024-35176/), users must update rexml to 3.2.7+ if they use it
2324
CVE-2024-27282 | Arbitrary memory address read vulnerability with Regex search | [Fix](https://github.com/ruby/ruby/commit/989a2355808a63fc45367785c82ffd46d18c900a) | | Not applicable thanks to Java semantics
2425
CVE-2024-27281 | RCE vulnerability with .rdoc_options in RDoc | [Fix](https://github.com/ruby/rdoc/compare/v6.3.3...v6.3.4.1) | | Not applicable because TruffleRuby does not generate rdoc on gem install

lib/cext/ABI_check.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1
1+
3

lib/truffle/stringio.rb

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,14 @@ def initialize(string = nil, mode = nil, **options)
166166
mode_from_string(string.frozen? ? 'r' : 'r+')
167167
end
168168

169+
if @writable && @__data__.string.frozen?
170+
raise Errno::EACCES, 'Permission denied'
171+
end
172+
173+
if @truncate
174+
@__data__.string.replace(''.force_encoding(@__data__.string.encoding))
175+
end
176+
169177
self
170178
end
171179

@@ -203,6 +211,22 @@ def set_encoding(external, internal = nil, options = nil)
203211
self
204212
end
205213

214+
def set_encoding_by_bom
215+
Primitive.check_frozen self
216+
return nil unless @readable
217+
218+
encoding = Truffle::IOOperations.strip_bom(self)
219+
return nil unless encoding
220+
221+
d = @__data__
222+
TruffleRuby.synchronized(d) do
223+
d.encoding = encoding
224+
d.string.force_encoding(encoding) if @writable
225+
end
226+
227+
encoding
228+
end
229+
206230
def external_encoding
207231
@__data__.encoding
208232
end
@@ -672,43 +696,37 @@ def yaml_initialize(type, val)
672696
end
673697

674698
private def mode_from_string(mode)
675-
@append = truncate = false
699+
@append = @truncate = false
676700

677701
if mode[0] == ?r
678702
@readable = true
679703
@writable = mode[-1] == ?+ ? true : false
680704
end
681705

682706
if mode[0] == ?w
683-
@writable = truncate = true
707+
@writable = @truncate = true
684708
@readable = mode[-1] == ?+ ? true : false
685709
end
686710

687711
if mode[0] == ?a
688712
@append = @writable = true
689713
@readable = mode[-1] == ?+ ? true : false
690714
end
691-
692-
d = @__data__ # no sync, only called from initialize
693-
raise Errno::EACCES, 'Permission denied' if @writable && d.string.frozen?
694-
d.string.replace('') if truncate
695715
end
696716

697717
private def mode_from_integer(mode)
698-
@readable = @writable = @append = false
699-
d = @__data__ # no sync, only called from initialize
718+
@readable = @writable = @append = @truncate = false
700719

701720
if mode == 0 or mode & IO::RDWR != 0
702721
@readable = true
703722
end
704723

705724
if mode & (IO::WRONLY | IO::RDWR) != 0
706-
raise Errno::EACCES, 'Permission denied' if d.string.frozen?
707725
@writable = true
708726
end
709727

710728
@append = true if (mode & IO::APPEND) != 0
711-
d.string.replace('') if (mode & IO::TRUNC) != 0
729+
@truncate = true if (mode & IO::TRUNC) != 0
712730
end
713731

714732
private def getline(arg_error, sep, limit, chomp = false)

lib/truffle/truffle/cext.rb

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,15 @@ def self.init_libtrufflerubytrampoline(libtrampoline)
190190

191191
init_functions = libtrampoline[:rb_tr_trampoline_init_functions]
192192
init_functions = Primitive.interop_eval_nfi('(env,(string):pointer):void').bind(init_functions)
193-
init_functions.call(-> name { LIBTRUFFLERUBY[name] })
193+
if Truffle::Boot.get_option 'cexts-panama' and Primitive.vm_java_version >= 22 and !TruffleRuby.native?
194+
init_functions.call(-> name {
195+
closure = LIBTRUFFLERUBY[name].createNativeClosure('panama')
196+
keep_alive << closure
197+
closure
198+
})
199+
else
200+
init_functions.call(-> name { LIBTRUFFLERUBY[name] })
201+
end
194202

195203
init_constants = libtrampoline[:rb_tr_trampoline_init_global_constants]
196204
init_constants = Primitive.interop_eval_nfi('((string):pointer):void').bind(init_constants)
@@ -713,7 +721,7 @@ def rb_reg_compile(pattern, options)
713721
nil
714722
end
715723
if err
716-
Primitive.thread_set_exception(err)
724+
Primitive.fiber_set_error_info(err)
717725
nil
718726
else
719727
result
@@ -1231,7 +1239,7 @@ def rb_protect(function, arg, write_status, status)
12311239
unless Primitive.nil?(e)
12321240
store_exception(e)
12331241
pos = extract_tag(e)
1234-
Primitive.thread_set_exception(extract_ruby_exception(e))
1242+
Primitive.fiber_set_error_info(extract_ruby_exception(e))
12351243
end
12361244

12371245
Truffle::Interop.execute_without_conversion(write_status, status, pos)
@@ -1244,7 +1252,7 @@ def rb_jump_tag(pos)
12441252
e = retrieve_exception
12451253
tag = extract_tag(e)
12461254
raise RuntimeError, 'mismatch between jump tag and captured exception' unless pos == tag
1247-
Primitive.thread_set_exception(nil)
1255+
Primitive.fiber_set_error_info(nil)
12481256
raise_exception(e)
12491257
end
12501258
end
@@ -1299,7 +1307,7 @@ def rb_exc_raise(exception)
12991307

13001308
def rb_set_errinfo(error)
13011309
if Primitive.nil?(error) || Primitive.is_a?(error, Exception)
1302-
Primitive.thread_set_exception(error)
1310+
Primitive.fiber_set_error_info(error)
13031311
else
13041312
raise TypeError, 'assigning non-exception to ?!'
13051313
end
@@ -1310,7 +1318,7 @@ def rb_make_exception(args)
13101318
end
13111319

13121320
def rb_errinfo
1313-
$!
1321+
Primitive.fiber_get_error_info
13141322
end
13151323

13161324
def rb_arity_error_string(arg_count, min, max)
@@ -1486,7 +1494,7 @@ def rb_get_alloc_func(ruby_class)
14861494
begin
14871495
allocate_method = ruby_class.method(:__allocate__).owner
14881496
rescue NameError
1489-
nil
1497+
nil # it's fine to call this on a class that doesn't have an allocator
14901498
else
14911499
Primitive.object_hidden_var_get(allocate_method, ALLOCATOR_FUNC)
14921500
end
@@ -1611,7 +1619,7 @@ def rb_mutex_sleep(mutex, timeout)
16111619

16121620
def rb_mutex_synchronize(mutex, func, arg)
16131621
mutex.synchronize do
1614-
Primitive.cext_unwrap(Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [func, arg]))
1622+
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [func, arg])
16151623
end
16161624
end
16171625
Truffle::Graal.always_split instance_method(:rb_mutex_synchronize)
@@ -1784,6 +1792,14 @@ def rb_f_notimplement
17841792
raise NotImplementedError, "#{function}() function is unimplemented on this machine"
17851793
end
17861794

1795+
def rb_bug(message)
1796+
raise Exception, "rb_bug: #{message}"
1797+
end
1798+
1799+
def rb_fatal(message)
1800+
raise Exception, "rb_fatal: #{message}"
1801+
end
1802+
17871803
def test_kwargs(kwargs, raise_error)
17881804
return false if Primitive.nil?(kwargs)
17891805

@@ -1821,19 +1837,31 @@ def rb_ensure(b_proc, data1, e_proc, data2)
18211837
begin
18221838
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [b_proc, data1])
18231839
ensure
1824-
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [e_proc, data2])
1840+
errinfo = Primitive.fiber_get_error_info
1841+
Primitive.fiber_set_error_info($!)
1842+
begin
1843+
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [e_proc, data2])
1844+
ensure
1845+
Primitive.fiber_set_error_info(errinfo)
1846+
end
18251847
end
18261848
end
18271849
Truffle::Graal.always_split instance_method(:rb_ensure)
18281850

18291851
def rb_rescue(b_proc, data1, r_proc, data2)
18301852
begin
18311853
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [b_proc, data1])
1832-
rescue StandardError => e
1854+
rescue StandardError => exc
18331855
if Truffle::Interop.null?(r_proc)
18341856
Primitive.cext_wrap(nil)
18351857
else
1836-
Primitive.interop_execute(POINTER2_TO_POINTER_WRAPPER, [r_proc, data2, Primitive.cext_wrap(e)])
1858+
errinfo = Primitive.fiber_get_error_info
1859+
Primitive.fiber_set_error_info(exc)
1860+
begin
1861+
Primitive.interop_execute(POINTER2_TO_POINTER_WRAPPER, [r_proc, data2, Primitive.cext_wrap(exc)])
1862+
ensure
1863+
Primitive.fiber_set_error_info(errinfo)
1864+
end
18371865
end
18381866
end
18391867
end
@@ -1842,8 +1870,14 @@ def rb_rescue(b_proc, data1, r_proc, data2)
18421870
def rb_rescue2(b_proc, data1, r_proc, data2, rescued)
18431871
begin
18441872
Primitive.interop_execute(POINTER_TO_POINTER_WRAPPER, [b_proc, data1])
1845-
rescue *rescued => e
1846-
Primitive.interop_execute(POINTER2_TO_POINTER_WRAPPER, [r_proc, data2, Primitive.cext_wrap(e)])
1873+
rescue *rescued => exc
1874+
errinfo = Primitive.fiber_get_error_info
1875+
Primitive.fiber_set_error_info(exc)
1876+
begin
1877+
Primitive.interop_execute(POINTER2_TO_POINTER_WRAPPER, [r_proc, data2, Primitive.cext_wrap(exc)])
1878+
ensure
1879+
Primitive.fiber_set_error_info(errinfo)
1880+
end
18471881
end
18481882
end
18491883
Truffle::Graal.always_split instance_method(:rb_rescue2)

lib/truffle/truffle/cext_preprocessor.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
# rubocop:disable TruffleRuby/*
1212

1313
require_relative 'patches/json_patches'
14-
require_relative 'patches/nokogiri_patches'
1514
require_relative 'patches/oci8_patches'
1615
require_relative 'patches/pg_patches'
1716
require_relative 'patches/tk_patches'
@@ -42,7 +41,6 @@ def self.add_gem_patches(patch_hash, gem_patches)
4241
end
4342

4443
add_gem_patches(PATCHED_FILES, ::JsonPatches::PATCHES)
45-
add_gem_patches(PATCHED_FILES, ::NokogiriPatches::PATCHES)
4644
add_gem_patches(PATCHED_FILES, ::OCI8Patches::PATCHES)
4745
add_gem_patches(PATCHED_FILES, ::PgPatches::PATCHES)
4846
add_gem_patches(PATCHED_FILES, ::TkPatches::PATCHES)

lib/truffle/truffle/cext_ruby.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,9 @@ def rb_define_method(mod, name, function, argc)
3333
args = [function, Primitive.cext_wrap(self), *args.map! { |arg| Primitive.cext_wrap(arg) }]
3434
end
3535

36-
exc = $!
37-
Primitive.thread_set_exception(nil)
3836
# We must set block argument if given here so that the
3937
# `rb_block_*` functions will be able to find it by walking the stack.
40-
res = Primitive.call_with_c_mutex_and_frame_and_unwrap(wrapper, args, Primitive.caller_special_variables_if_available, block)
41-
Primitive.thread_set_exception(exc)
42-
res
38+
Primitive.call_with_c_mutex_and_frame_and_unwrap(wrapper, args, Primitive.caller_special_variables_if_available, block)
4339
end
4440

4541
# Even if the argc is -2, the arity number

0 commit comments

Comments
 (0)