summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/json/json_ext_parser_test.rb2
-rw-r--r--test/objspace/test_objspace.rb15
-rw-r--r--test/ruby/test_ractor.rb11
-rw-r--r--test/rubygems/test_gem_installer.rb124
-rw-r--r--test/rubygems/test_gem_text.rb17
-rw-r--r--test/socket/test_ancdata.rb18
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