diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/json/json_ext_parser_test.rb | 2 | ||||
| -rw-r--r-- | test/objspace/test_objspace.rb | 15 | ||||
| -rw-r--r-- | test/ruby/test_ractor.rb | 11 | ||||
| -rw-r--r-- | test/rubygems/test_gem_installer.rb | 124 | ||||
| -rw-r--r-- | test/rubygems/test_gem_text.rb | 17 | ||||
| -rw-r--r-- | test/socket/test_ancdata.rb | 18 |
6 files changed, 186 insertions, 1 deletions
diff --git a/test/json/json_ext_parser_test.rb b/test/json/json_ext_parser_test.rb index e610f642f1..d585b8d0dc 100644 --- a/test/json/json_ext_parser_test.rb +++ b/test/json/json_ext_parser_test.rb @@ -26,7 +26,7 @@ class JSONExtParserTest < Test::Unit::TestCase ex = assert_raise(ParserError) { parse('-Infinity something') } unless RUBY_PLATFORM =~ /java/ - assert_equal "unexpected token '-Infinity' at line 1 column 1", ex.message + assert_equal "invalid number: '-Infinity' at line 1 column 1", ex.message end ex = assert_raise(ParserError) { parse('NaN something') } diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index faa22f1424..a9b902ed45 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -350,6 +350,21 @@ class TestObjSpace < Test::Unit::TestCase RUBY end + def test_trace_object_allocations_does_not_reuse_freed_allocation_info + assert_separately(%w(-robjspace), <<~RUBY) + ObjectSpace.trace_object_allocations do + 1_000_000.times.map { Object.new } + end + + GC.start + + objs = 1_000_000.times.map { Object.new } + + leaked = objs.count { |obj| ObjectSpace.allocation_sourcefile(obj) } + assert_equal 0, leaked + RUBY + end + def test_dump_flags # Ensure that the fstring is promoted to old generation 4.times { GC.start } diff --git a/test/ruby/test_ractor.rb b/test/ruby/test_ractor.rb index 611b3b7715..e7eb0cd4b3 100644 --- a/test/ruby/test_ractor.rb +++ b/test/ruby/test_ractor.rb @@ -321,6 +321,17 @@ class TestRactor < Test::Unit::TestCase RUBY end + def test_mn_threads + # Ideally, we would assert that vm->ractor.sched.max_cpu equals sysconf(_SC_NPROCESSORS_ONLN) + # when RUBY_MAX_CPU is not set. + assert_ractor(<<~'RUBY', args: [{ "RUBY_MN_THREADS" => "1" }]) + require "etc" + n = Etc.respond_to?(:nprocessors) ? Etc.nprocessors : 8 + rs = n.times.map { Ractor.new { :ok } } + assert_equal [:ok] * n, rs.map(&:value) + RUBY + end + def test_symbol_proc_is_shareable pr = :symbol.to_proc assert_make_shareable(pr) diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index bf7a4a8dfc..8947694f53 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -60,6 +60,21 @@ class TestGemInstaller < Gem::InstallerTestCase end end + def test_app_script_text_escapes_executable_name + installer = setup_base_installer + + malicious = "evil');system('id');#" + @spec.bindir = "bin" + write_file @spec.bin_file(malicious) do |io| + io.puts "#!/usr/bin/ruby" + end + + wrapper = installer.app_script_text malicious + + assert_includes wrapper, %q{Gem.activate_and_load_bin_path('a', 'evil\');system(\'id\');#', version)} + assert_includes wrapper, %q{load Gem.activate_bin_path('a', 'evil\');system(\'id\');#', version)} + end + def test_check_executable_overwrite installer = setup_base_installer @@ -1481,6 +1496,39 @@ class TestGemInstaller < Gem::InstallerTestCase refute_match(/I am a shiny gem!/, @ui.output) end + def test_install_sanitizes_post_install_message + # Use for_spec so the in-memory message reaches the installer verbatim; + # building a gem would escape the control characters during serialization. + @spec = setup_base_spec + @spec.post_install_message = "shiny \e]2;pwn\a gem" + + installer = Gem::Installer.for_spec @spec, post_install_message: true + installer.gem_home = @gemhome + + use_ui @ui do + installer.install + end + + assert_match(/shiny \.\]2;pwn\. gem/, @ui.output) + refute_match(/\e\]2;pwn/, @ui.output) + end + + def test_install_handles_non_string_post_install_message + # post_install_message may be a non-String (the gemspec schema allows an + # array), so sanitizing must not assume it responds to gsub. + @spec = setup_base_spec + @spec.post_install_message = %w[one two] + + installer = Gem::Installer.for_spec @spec, post_install_message: true + installer.gem_home = @gemhome + + use_ui @ui do + installer.install + end + + assert_match(/one/, @ui.output) + end + def test_install_extension_dir gemhome2 = "#{@gemhome}2" @@ -1921,6 +1969,82 @@ class TestGemInstaller < Gem::InstallerTestCase end end + def test_pre_install_checks_malicious_executables_before_eval + spec = util_spec "malicious", "1" + def spec.full_name # so the spec is buildable + "malicious-1" + end + + def spec.validate(*args); end + spec.executables = ["../../../tmp/malicious"] + + util_build_gem spec + + gem = File.join(@gemhome, "cache", spec.file_name) + + use_ui @ui do + installer = Gem::Installer.at gem + e = assert_raise Gem::InstallError do + installer.pre_install_checks + end + assert_equal "#<Gem::Specification name=malicious version=1> has an invalid executable", e.message + end + end + + def test_pre_install_checks_malicious_bindir_before_eval + spec = util_spec "malicious", "1" + def spec.full_name # so the spec is buildable + "malicious-1" + end + + def spec.validate(*args); end + spec.bindir = "../../../tmp/malicious" + + util_build_gem spec + + gem = File.join(@gemhome, "cache", spec.file_name) + + use_ui @ui do + installer = Gem::Installer.at gem + e = assert_raise Gem::InstallError do + installer.pre_install_checks + end + assert_equal "#<Gem::Specification name=malicious version=1> has an invalid bindir", e.message + end + end + + def test_pre_install_checks_non_string_executable + spec = util_spec "malicious", "1" + def spec.validate(*args); end + spec.executables = [nil] + + installer = Gem::Installer.for_spec spec + installer.gem_home = @gemhome + + use_ui @ui do + e = assert_raise Gem::InstallError do + installer.pre_install_checks + end + assert_equal "#<Gem::Specification name=malicious version=1> has an invalid executable", e.message + end + end + + def test_pre_install_checks_non_string_bindir + spec = util_spec "malicious", "1" + def spec.validate(*args); end + spec.bindir = true + + installer = Gem::Installer.for_spec spec + installer.gem_home = @gemhome + + use_ui @ui do + e = assert_raise Gem::InstallError do + installer.pre_install_checks + end + assert_equal "#<Gem::Specification name=malicious version=1> has an invalid bindir", e.message + end + end + def test_pre_install_checks_malicious_platform_before_eval gem_with_ill_formatted_platform = File.expand_path("packages/ill-formatted-platform-1.0.0.10.gem", __dir__) diff --git a/test/rubygems/test_gem_text.rb b/test/rubygems/test_gem_text.rb index 8e99610946..60739e6131 100644 --- a/test/rubygems/test_gem_text.rb +++ b/test/rubygems/test_gem_text.rb @@ -100,4 +100,21 @@ Without the wrapping, the text might not look good in the RSS feed. def test_clean_text assert_equal ".]2;nyan.", clean_text("\e]2;nyan\a") end + + def test_clean_text_strips_c1_control_characters + text = [0x41, 0x9b, 0x42].pack("U*") # "A", CSI (U+009B), "B" + assert_equal "A.B", clean_text(text) + end + + def test_clean_text_preserves_multibyte_characters + # U+0400 encodes to bytes D0 80, whose 0x80 continuation byte must not be + # mistaken for a C1 control byte. NEL (U+0085) is stripped. + text = [0x400, 0x85].pack("U*") + assert_equal [0x400, 0x2e].pack("U*"), clean_text(text) + end + + def test_clean_text_passes_through_non_unicode_encodings + text = "x\x9by".dup.force_encoding("ISO-8859-1") + assert_equal text, clean_text(text) + end end diff --git a/test/socket/test_ancdata.rb b/test/socket/test_ancdata.rb index b2f86a0bb1..387be6080f 100644 --- a/test/socket/test_ancdata.rb +++ b/test/socket/test_ancdata.rb @@ -65,4 +65,22 @@ class TestSocketAncData < Test::Unit::TestCase } end end + + if /freebsd/ =~ RUBY_PLATFORM + def test_cmsgcred_inspect + cred = [0, 0, 0, 0, 9999, *Array.new(16, 0)].pack('L4I!L*') + s = Socket::AncillaryData.new(:UNIX, :SOCKET, :SCM_CREDS, cred).inspect + assert_include(s, 'groups[9999]') + assert_include(s, '(cmsgcred)') + end + end + + if /netbsd|freebsd/ =~ RUBY_PLATFORM + def test_sockcred_inspect + cred = [0, 0, 0, 0, 9999, 0].pack('L4S!L') + s = Socket::AncillaryData.new(:UNIX, :SOCKET, :SCM_CREDS, cred).inspect + assert_include(s, 'groups[9999]') + assert_include(s, '(sockcred)') + end + end end if defined? Socket::AncillaryData |
