[rubygems/rubygems] All rubies working with different time zones

Tested with:

`ruby -e 'trap("INT") { exit 1 }; TZ=%w[UTC +0000 -0000]; RUBY=%w[ruby-2.7 ruby-3.2.2 jruby-9.4 truffleruby-22 truffleruby-23]; TZ.product(RUBY).each { |t, r| puts ?**120, "TZ=#{t} RUBY=#{r}", "*"*120; system({"TZ"=>t,"RUBY"=>r}, *ARGV) }' zsh -lic 'chruby $RUBY; ruby -vw -Ilib test/rubygems/test_gem_safe_marshal.rb --verbose=progress'`

https://github.com/rubygems/rubygems/commit/6192005afb
This commit is contained in:
Samuel Giddins 2023-08-24 09:23:02 -07:00 committed by git
parent c65c88e65c
commit cadca9f67e
3 changed files with 30 additions and 9 deletions

View File

@ -42,7 +42,7 @@ module Gem
private_constant :PERMITTED_SYMBOLS private_constant :PERMITTED_SYMBOLS
PERMITTED_IVARS = { PERMITTED_IVARS = {
"String" => %w[E @taguri @debug_created_info], "String" => %w[E encoding @taguri @debug_created_info],
"Time" => %w[ "Time" => %w[
offset zone nano_num nano_den submicro offset zone nano_num nano_den submicro
@_zone @marshal_with_utc_coercion @_zone @marshal_with_utc_coercion

View File

@ -54,7 +54,6 @@ module Gem::SafeMarshal
end end
def visit_Gem_SafeMarshal_Elements_WithIvars(e) def visit_Gem_SafeMarshal_Elements_WithIvars(e)
idx = 0
object_offset = @objects.size object_offset = @objects.size
@stack << "object" @stack << "object"
object = visit(e.object) object = visit(e.object)
@ -104,8 +103,9 @@ module Gem::SafeMarshal
if zone if zone
require "time" require "time"
zone = "+0000" if zone == "UTC" && offset == 0 transformed_zone = zone
call_method(Time, :force_zone!, object, zone, offset) transformed_zone = "+0000" if ["UTC", "Z"].include?(zone) && offset == 0
call_method(Time, :force_zone!, object, transformed_zone, offset)
elsif offset elsif offset
object = object.localtime offset object = object.localtime offset
end end
@ -131,8 +131,10 @@ module Gem::SafeMarshal
when FalseClass when FalseClass
enc = "US-ASCII" enc = "US-ASCII"
else else
enc = v raise FormatError, "Unexpected value for String :E #{v.inspect}"
end end
when :encoding
enc = v
else else
next false next false
end end

View File

@ -36,8 +36,16 @@ class TestGemSafeMarshal < Gem::TestCase
end end
def test_string_with_encoding def test_string_with_encoding
assert_safe_load_as String.new("abc", encoding: "US-ASCII") [
assert_safe_load_as String.new("abc", encoding: "UTF-8") String.new("abc", encoding: "US-ASCII"),
String.new("abc", encoding: "UTF-8"),
String.new("abc", encoding: "Windows-1256"),
String.new("abc", encoding: Encoding::BINARY),
String.new("abc", encoding: "UTF-32"),
].each do |s|
assert_safe_load_as s, additional_methods: [:encoding]
assert_safe_load_as [s, s], additional_methods: [->(a) { a.map(&:encoding) }]
end
end end
def test_string_with_ivar def test_string_with_ivar
@ -75,7 +83,12 @@ class TestGemSafeMarshal < Gem::TestCase
Time.at(secs, 1.001, :nanosecond), Time.at(secs, 1.001, :nanosecond),
Time.at(secs, 1.00001, :nanosecond), Time.at(secs, 1.00001, :nanosecond),
Time.at(secs, 1.00001, :nanosecond), Time.at(secs, 1.00001, :nanosecond),
].each_with_index do |t, i| ].tap do |times|
times.concat [
Time.at(secs, in: "UTC"),
Time.at(secs, in: "Z"),
] unless RUBY_ENGINE == "truffleruby" && RUBY_ENGINE_VERSION < "23"
end.each_with_index do |t, i|
define_method("test_time_#{i} #{t.inspect}") do define_method("test_time_#{i} #{t.inspect}") do
pend "Marshal.load of Time with custom zone is broken before Truffleruby 23" if t.zone.nil? && RUBY_ENGINE == "truffleruby" && RUBY_ENGINE_VERSION < "23" pend "Marshal.load of Time with custom zone is broken before Truffleruby 23" if t.zone.nil? && RUBY_ENGINE == "truffleruby" && RUBY_ENGINE_VERSION < "23"
@ -167,7 +180,13 @@ class TestGemSafeMarshal < Gem::TestCase
assert_equal x.to_s, safe_loaded.to_s, "should have equal to_s" assert_equal x.to_s, safe_loaded.to_s, "should have equal to_s"
assert_equal x.inspect, safe_loaded.inspect, "should have equal inspect" assert_equal x.inspect, safe_loaded.inspect, "should have equal inspect"
additional_methods.each do |m| additional_methods.each do |m|
assert_equal loaded.send(m), safe_loaded.send(m), "should have equal #{m}" if m.is_a?(Proc)
call = m
else
call = ->(obj) { obj.__send__(m) }
end
assert_equal call[loaded], call[safe_loaded], "should have equal #{m}"
end end
assert_equal Marshal.dump(loaded), Marshal.dump(safe_loaded), "should Marshal.dump the same" assert_equal Marshal.dump(loaded), Marshal.dump(safe_loaded), "should Marshal.dump the same"
end end