diff --git a/lib/tzinfo/ruby_core_support.rb b/lib/tzinfo/ruby_core_support.rb index 7ba776b3..27633d09 100644 --- a/lib/tzinfo/ruby_core_support.rb +++ b/lib/tzinfo/ruby_core_support.rb @@ -153,16 +153,23 @@ def self.open_file(file_name, mode, opts, &block) end - # Object#untaint is a deprecated no-op in Ruby >= 2.7 and will be removed in - # 3.2. Add a refinement to either silence the warning, or supply the method - # if needed. + # Object#untaint is deprecated and becomes a no-op in Ruby >= 2.7. It has + # been removed from Ruby 3.2. if !Object.new.respond_to?(:untaint) || RUBY_VERSION =~ /\A(\d+)\.(\d+)(?:\.|\z)/ && ($1 == '2' && $2.to_i >= 7 || $1.to_i >= 3) - module UntaintExt - refine Object do - def untaint - self - end - end + # Returns the supplied `Object` + # + # @param o [Object] the `Object` to untaint. + # @return [Object] `o`. + def self.untaint(o) + o + end + else + # Untaints and returns the supplied `Object`. + # + # @param o [Object] the `Object` to untaint. + # @return [Object] `o`. + def self.untaint(o) + o.untaint end end end diff --git a/lib/tzinfo/ruby_data_source.rb b/lib/tzinfo/ruby_data_source.rb index 792ca820..fd0b0878 100644 --- a/lib/tzinfo/ruby_data_source.rb +++ b/lib/tzinfo/ruby_data_source.rb @@ -1,8 +1,4 @@ module TZInfo - # Use send as a workaround for erroneous 'wrong number of arguments' errors - # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114. - send(:using, RubyCoreSupport::UntaintExt) if RubyCoreSupport.const_defined?(:UntaintExt) - # A DataSource that loads data from the set of Ruby modules included in the # TZInfo::Data library (tzinfo-data gem). # @@ -25,7 +21,7 @@ def initialize data_file = File.join('', 'tzinfo', 'data.rb') path = $".reverse_each.detect {|p| p.end_with?(data_file) } if path - @base_path = File.join(File.dirname(path), 'data').untaint + @base_path = RubyCoreSupport.untaint(File.join(File.dirname(path), 'data')) else @base_path = tzinfo_data end @@ -45,7 +41,7 @@ def load_timezone_info(identifier) # Untaint identifier after it has been reassigned to a new string. We # don't want to modify the original identifier. identifier may also be # frozen and therefore cannot be untainted. - identifier.untaint + RubyCoreSupport.untaint(identifier) identifier = identifier.split('/') begin diff --git a/lib/tzinfo/zoneinfo_data_source.rb b/lib/tzinfo/zoneinfo_data_source.rb index 5cbc6947..2fa83d50 100644 --- a/lib/tzinfo/zoneinfo_data_source.rb +++ b/lib/tzinfo/zoneinfo_data_source.rb @@ -1,12 +1,4 @@ module TZInfo - # Use send as a workaround for an issue on JRuby 9.2.9.0 where using the - # refinement causes calls to RubyCoreSupport.file_open to fail to pass the - # block parameter. - # - # https://travis-ci.org/tzinfo/tzinfo/jobs/628812051#L1931 - # https://github.com/jruby/jruby/issues/6009 - send(:using, TZInfo::RubyCoreSupport::UntaintExt) if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt) - # An InvalidZoneinfoDirectory exception is raised if the DataSource is # set to a specific zoneinfo path, which is not a valid zoneinfo directory # (i.e. a directory containing index files named iso3166.tab and zone.tab @@ -229,7 +221,7 @@ def load_timezone_info(identifier) # Untaint path rather than identifier. We don't want to modify # identifier. identifier may also be frozen and therefore cannot be # untainted. - path.untaint + RubyCoreSupport.untaint(path) begin ZoneinfoTimezoneInfo.new(identifier, path, @posix_tz_parser) @@ -388,7 +380,7 @@ def load_timezone_index def enum_timezones(dir, exclude = [], &block) Dir.foreach(dir ? File.join(@zoneinfo_dir, dir) : @zoneinfo_dir) do |entry| unless entry =~ /\./ || exclude.include?(entry) - entry.untaint + RubyCoreSupport.untaint(entry) path = dir ? File.join(dir, entry) : entry full_path = File.join(@zoneinfo_dir, path) diff --git a/lib/tzinfo/zoneinfo_timezone_info.rb b/lib/tzinfo/zoneinfo_timezone_info.rb index a2fa9954..1551d74f 100644 --- a/lib/tzinfo/zoneinfo_timezone_info.rb +++ b/lib/tzinfo/zoneinfo_timezone_info.rb @@ -1,8 +1,4 @@ module TZInfo - # Use send as a workaround for erroneous 'wrong number of arguments' errors - # with JRuby 9.0.5.0 when calling methods with Java implementations. See #114. - send(:using, RubyCoreSupport::UntaintExt) if RubyCoreSupport.const_defined?(:UntaintExt) - # An InvalidZoneinfoFile exception is raised if an attempt is made to load an # invalid zoneinfo file. class InvalidZoneinfoFile < StandardError @@ -351,7 +347,7 @@ def define_offset(index, offset) std_offset = 0 end - offset index, utc_offset, std_offset, offset[:abbr].untaint.to_sym + offset index, utc_offset, std_offset, RubyCoreSupport.untaint(offset[:abbr]).to_sym end # Parses a zoneinfo file and intializes the DataTimezoneInfo structures. diff --git a/test/tc_country.rb b/test/tc_country.rb index faa3bb52..c4ab10e7 100644 --- a/test/tc_country.rb +++ b/test/tc_country.rb @@ -2,10 +2,6 @@ include TZInfo -# Use send as a workaround for erroneous 'wrong number of arguments' errors with -# JRuby 9.0.5.0 when calling methods with Java implementations. See #114. -send(:using, TaintExt) if Module.const_defined?(:TaintExt) - class TCCountry < Minitest::Test def setup @orig_data_source = DataSource.get @@ -48,6 +44,7 @@ def test_get_case end def test_get_tainted_loaded + skip_if_taint_is_undefined_or_no_op Country.get('GB') safe_test(:unavailable => :skip) do @@ -60,6 +57,7 @@ def test_get_tainted_loaded end def test_get_tainted_and_frozen_loaded + skip_if_taint_is_undefined_or_no_op Country.get('GB') safe_test do @@ -69,6 +67,8 @@ def test_get_tainted_and_frozen_loaded end def test_get_tainted_not_previously_loaded + skip_if_taint_is_undefined_or_no_op + safe_test(:unavailable => :skip) do code = 'GB'.dup.taint assert(code.tainted?) @@ -79,6 +79,8 @@ def test_get_tainted_not_previously_loaded end def test_get_tainted_and_frozen_not_previously_loaded + skip_if_taint_is_undefined_or_no_op + safe_test do country = Country.get('GB'.dup.taint.freeze) assert_equal('GB', country.code) diff --git a/test/tc_ruby_data_source.rb b/test/tc_ruby_data_source.rb index 23ecdfab..4250d5bf 100644 --- a/test/tc_ruby_data_source.rb +++ b/test/tc_ruby_data_source.rb @@ -2,10 +2,6 @@ include TZInfo -# Use send as a workaround for erroneous 'wrong number of arguments' errors with -# JRuby 9.0.5.0 when calling methods with Java implementations. See #114. -send(:using, TaintExt) if Module.const_defined?(:TaintExt) - class TCRubyDataSource < Minitest::Test def setup @data_source = RubyDataSource.new @@ -81,6 +77,7 @@ def test_load_timezone_info_minus end def test_load_timezone_info_tainted + skip_if_taint_is_undefined_or_no_op skip_if_has_bug_14060 safe_test(:unavailable => :skip) do @@ -93,6 +90,7 @@ def test_load_timezone_info_tainted end def test_load_timezone_info_tainted_and_frozen + skip_if_taint_is_undefined_or_no_op skip_if_has_bug_14060 safe_test do @@ -149,6 +147,8 @@ def test_load_country_info_case end def test_load_country_info_tainted + skip_if_taint_is_undefined_or_no_op + safe_test(:unavailable => :skip) do code = 'NL'.dup.taint assert(code.tainted?) @@ -159,6 +159,8 @@ def test_load_country_info_tainted end def test_load_country_info_tainted_and_frozen + skip_if_taint_is_undefined_or_no_op + safe_test do info = @data_source.load_country_info('NL'.dup.taint.freeze) assert_equal('NL', info.code) diff --git a/test/tc_timezone.rb b/test/tc_timezone.rb index 5f4614d3..51c2bf8d 100644 --- a/test/tc_timezone.rb +++ b/test/tc_timezone.rb @@ -2,10 +2,6 @@ include TZInfo -# Use send as a workaround for erroneous 'wrong number of arguments' errors with -# JRuby 9.0.5.0 when calling methods with Java implementations. See #114. -send(:using, TaintExt) if Module.const_defined?(:TaintExt) - class TCTimezone < Minitest::Test class BlockCalled < StandardError @@ -244,6 +240,7 @@ def test_get_proxy_invalid end def test_get_tainted_loaded + skip_if_taint_is_undefined_or_no_op Timezone.get('Europe/Andorra') safe_test(:unavailable => :skip) do @@ -256,6 +253,7 @@ def test_get_tainted_loaded end def test_get_tainted_and_frozen_loaded + skip_if_taint_is_undefined_or_no_op Timezone.get('Europe/Andorra') safe_test do @@ -265,6 +263,7 @@ def test_get_tainted_and_frozen_loaded end def test_get_tainted_not_previously_loaded + skip_if_taint_is_undefined_or_no_op skip_if_has_bug_14060 safe_test(:unavailable => :skip) do @@ -277,6 +276,7 @@ def test_get_tainted_not_previously_loaded end def test_get_tainted_and_frozen_not_previously_loaded + skip_if_taint_is_undefined_or_no_op skip_if_has_bug_14060 safe_test do diff --git a/test/tc_zoneinfo_data_source.rb b/test/tc_zoneinfo_data_source.rb index e0afe5fc..f9864dc9 100644 --- a/test/tc_zoneinfo_data_source.rb +++ b/test/tc_zoneinfo_data_source.rb @@ -7,17 +7,8 @@ include TZInfo -# Use send as a workaround for an issue on JRuby 9.2.9.0 where using the -# refinement causes calls to RubyCoreSupport.file_open to fail to pass the block -# parameter. -# -# https://travis-ci.org/tzinfo/tzinfo/jobs/628812051#L1931 -# https://github.com/jruby/jruby/issues/6009 -send(:using, TZInfo::RubyCoreSupport::UntaintExt) if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt) -send(:using, TaintExt) if Module.const_defined?(:TaintExt) - class TCZoneinfoDataSource < Minitest::Test - ZONEINFO_DIR = File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo').untaint + ZONEINFO_DIR = RubyCoreSupport.untaint(File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo')) def setup @orig_search_path = ZoneinfoDataSource.search_path.clone @@ -662,6 +653,8 @@ def test_load_timezone_info_invalid_file_2 end def test_load_timezone_info_tainted + skip_if_taint_is_undefined_or_no_op + safe_test(:unavailable => :skip) do identifier = 'Europe/Amsterdam'.dup.taint assert(identifier.tainted?) @@ -672,6 +665,8 @@ def test_load_timezone_info_tainted end def test_load_timezone_info_tainted_and_frozen + skip_if_taint_is_undefined_or_no_op + safe_test do info = @data_source.load_timezone_info('Europe/Amsterdam'.dup.taint.freeze) assert_equal('Europe/Amsterdam', info.identifier) @@ -679,6 +674,8 @@ def test_load_timezone_info_tainted_and_frozen end def test_load_timezone_info_tainted_zoneinfo_dir_safe_mode + skip_if_taint_is_undefined_or_no_op + safe_test(:unavailable => :skip) do assert_raises(SecurityError) do ZoneinfoDataSource.new(@data_source.zoneinfo_dir.dup.taint) @@ -687,6 +684,8 @@ def test_load_timezone_info_tainted_zoneinfo_dir_safe_mode end def test_load_timezone_info_tainted_zoneinfo_dir + skip_if_taint_is_undefined_or_no_op + data_source = ZoneinfoDataSource.new(@data_source.zoneinfo_dir.dup.taint) info = data_source.load_timezone_info('Europe/London') assert_kind_of(ZoneinfoTimezoneInfo, info) @@ -697,7 +696,7 @@ def get_timezone_filenames(directory) entries = Dir.glob(File.join(directory, '**', '*')) entries = entries.select do |file| - file.untaint + RubyCoreSupport.untaint(file) File.file?(file) end @@ -868,6 +867,8 @@ def test_load_country_info_case end def test_load_country_info_tainted + skip_if_taint_is_undefined_or_no_op + safe_test(:unavailable => :skip) do code = 'NL'.dup.taint assert(code.tainted?) @@ -878,6 +879,8 @@ def test_load_country_info_tainted end def test_load_country_info_tainted_and_frozen + skip_if_taint_is_undefined_or_no_op + safe_test do info = @data_source.load_country_info('NL'.dup.taint.freeze) assert_equal('NL', info.code) diff --git a/test/tc_zoneinfo_timezone_info.rb b/test/tc_zoneinfo_timezone_info.rb index 7d66282e..6c6e962d 100644 --- a/test/tc_zoneinfo_timezone_info.rb +++ b/test/tc_zoneinfo_timezone_info.rb @@ -5,10 +5,6 @@ include TZInfo -# Use send as a workaround for erroneous 'wrong number of arguments' errors with -# JRuby 9.0.5.0 when calling methods with Java implementations. See #114. -send(:using, RubyCoreSupport::UntaintExt) if RubyCoreSupport.const_defined?(:UntaintExt) - class TCZoneinfoTimezoneInfo < Minitest::Test class FakePosixTimeZoneParser def initialize(&block) @@ -1281,7 +1277,7 @@ def test_load_in_safe_mode tzif_test(offsets, []) do |path, format| # untaint only required for Ruby 1.9.2 - path.untaint + RubyCoreSupport.untaint(path) safe_test do info = ZoneinfoTimezoneInfo.new('Zone/three', path, @posix_tz_parser) diff --git a/test/test_utils.rb b/test/test_utils.rb index 389d935a..2b0671d1 100644 --- a/test/test_utils.rb +++ b/test/test_utils.rb @@ -108,6 +108,25 @@ def skip_if_has_bug_14060 skip('Skipping test due to Ruby 2.4.4 being affected by Bug 14060 (see https://bugs.ruby-lang.org/issues/14060#note-5)') end end + + # Object#taint is deprecated in Ruby >= 2.7 and will be removed in 3.2. + # 2.7 makes it a no-op with a warning. + # Define a method that will skip for use in tests that deal with tainted + # objects. + if Object.respond_to?(:taint) + if RUBY_VERSION >= '2.7' + def skip_if_taint_is_undefined_or_no_op + skip('Object#taint is a no-op') + end + else + def skip_if_taint_is_undefined_or_no_op + end + end + else + def skip_if_taint_is_undefined_or_no_op + skip('Object#taint is not defined') + end + end def assert_array_same_items(expected, actual, msg = nil) full_message = message(msg, '') { diff(expected, actual) } @@ -184,19 +203,6 @@ def assert_nothing_raised(msg = nil) end -# Object#taint is a deprecated no-op in Ruby 2.7 and outputs a warning. It will -# be removed in 3.2. Silence the warning or supply a replacement. -if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt) - module TaintExt - refine Object do - def taint - self - end - end - end -end - - # JRuby 1.7.5 to 1.7.9 consider DateTime instances that differ by less than # 1 millisecond to be equivalent (https://github.com/jruby/jruby/issues/1311). # diff --git a/test/ts_all_zoneinfo.rb b/test/ts_all_zoneinfo.rb index ae1ba15e..6d6c67e2 100644 --- a/test/ts_all_zoneinfo.rb +++ b/test/ts_all_zoneinfo.rb @@ -3,7 +3,7 @@ # Use a zoneinfo directory containing files needed by the tests. # The symlinks in this directory are set up in test_utils.rb. zoneinfo_path = File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo') -zoneinfo_path.untaint if RUBY_VERSION < '2.7' +TZInfo.const_get(:RubyCoreSupport).untaint(zoneinfo_path) if RUBY_VERSION < '2.7' TZInfo::DataSource.set(:zoneinfo, zoneinfo_path) require File.join(File.expand_path(File.dirname(__FILE__)), 'ts_all.rb')