Merge pull request #2038 from eregon/truffleruby-ci

Add TruffleRuby in CI
This commit is contained in:
Kevin Menard
2026-03-25 11:53:01 -04:00
committed by GitHub
3 changed files with 45 additions and 28 deletions
+1
View File
@@ -22,6 +22,7 @@ jobs:
} }
- { ruby: 4.0, allowed-failure: false, rubyopt: "--yjit" } - { ruby: 4.0, allowed-failure: false, rubyopt: "--yjit" }
- { ruby: 4.0, allowed-failure: false, rubyopt: "--zjit" } - { ruby: 4.0, allowed-failure: false, rubyopt: "--zjit" }
- { ruby: truffleruby, allowed-failure: false }
# Head can have failures due to being in development # Head can have failures due to being in development
- { ruby: head, allowed-failure: true } - { ruby: head, allowed-failure: true }
+16 -7
View File
@@ -8,10 +8,19 @@ module Liquid
MAX_I32 = (1 << 31) - 1 MAX_I32 = (1 << 31) - 1
private_constant :MAX_I32 private_constant :MAX_I32
MIN_I64 = -(1 << 63) supports_64bit_indices = begin
MAX_I64 = (1 << 63) - 1 [][1 << 33, 1 << 33]
I64_RANGE = MIN_I64..MAX_I64 true
private_constant :MIN_I64, :MAX_I64, :I64_RANGE rescue RangeError
false
end
INDEX_RANGE = if supports_64bit_indices
(-(1 << 63))..((1 << 63) - 1)
else
(-(1 << 31))..((1 << 31) - 1)
end
private_constant :INDEX_RANGE
HTML_ESCAPE = { HTML_ESCAPE = {
'&' => '&amp;', '&' => '&amp;',
@@ -214,11 +223,11 @@ module Liquid
Utils.to_s(input).slice(offset, length) || '' Utils.to_s(input).slice(offset, length) || ''
end end
rescue RangeError rescue RangeError
if I64_RANGE.cover?(length) && I64_RANGE.cover?(offset) if INDEX_RANGE.cover?(length) && INDEX_RANGE.cover?(offset)
raise # unexpected error raise # unexpected error
end end
offset = offset.clamp(I64_RANGE) offset = offset.clamp(INDEX_RANGE)
length = length.clamp(I64_RANGE) length = length.clamp(INDEX_RANGE)
retry retry
end end
end end
+28 -21
View File
@@ -44,32 +44,39 @@ class SecurityTest < Minitest::Test
end end
def test_does_not_permanently_add_filters_to_symbol_table def test_does_not_permanently_add_filters_to_symbol_table
current_symbols = Symbol.all_symbols assert_no_new_symbols do
# MRI imprecisely marks objects found on the C stack, which can result
# in uninitialized memory being marked. This can even result in the test failing
# deterministically for a given compilation of ruby. Using a separate thread will
# keep these writes of the symbol pointer on a separate stack that will be garbage
# collected after Thread#join.
Thread.new do
test = %( {{ "some_string" | a_bad_filter }} )
Template.parse(test).render!
nil
end.join
# MRI imprecisely marks objects found on the C stack, which can result GC.start
# in uninitialized memory being marked. This can even result in the test failing end
# deterministically for a given compilation of ruby. Using a separate thread will
# keep these writes of the symbol pointer on a separate stack that will be garbage
# collected after Thread#join.
Thread.new do
test = %( {{ "some_string" | a_bad_filter }} )
Template.parse(test).render!
nil
end.join
GC.start
assert_equal([], Symbol.all_symbols - current_symbols)
end end
def test_does_not_add_drop_methods_to_symbol_table def test_does_not_add_drop_methods_to_symbol_table
assert_no_new_symbols do
assigns = { 'drop' => Drop.new }
assert_equal("", Template.parse("{{ drop.custom_method_1 }}", assigns).render!)
assert_equal("", Template.parse("{{ drop.custom_method_2 }}", assigns).render!)
assert_equal("", Template.parse("{{ drop.custom_method_3 }}", assigns).render!)
end
end
def assert_no_new_symbols
# Run once to trigger any first-time initialization which might create some symbols,
# for example autoload or lazy method parsing might create symbols on first execution.
yield
# Ensure no new symbols for further runs, i.e. the code does not leak symbols
current_symbols = Symbol.all_symbols current_symbols = Symbol.all_symbols
yield
assigns = { 'drop' => Drop.new }
assert_equal("", Template.parse("{{ drop.custom_method_1 }}", assigns).render!)
assert_equal("", Template.parse("{{ drop.custom_method_2 }}", assigns).render!)
assert_equal("", Template.parse("{{ drop.custom_method_3 }}", assigns).render!)
assert_equal([], Symbol.all_symbols - current_symbols) assert_equal([], Symbol.all_symbols - current_symbols)
end end