From c24019355393a33c7412a84db90b8fbadb68a7ee Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 25 Aug 2026 12:46:14 +0900 Subject: [PATCH 1/3] Scrub off the invalid sequence Since the base `string` is a valid encoding, there should be no other invalid sequences in `sliced`. --- lib/rubygems/util/atomic_file_writer.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/rubygems/util/atomic_file_writer.rb b/lib/rubygems/util/atomic_file_writer.rb index be9bf76e83b8..c3be873c9eba 100644 --- a/lib/rubygems/util/atomic_file_writer.rb +++ b/lib/rubygems/util/atomic_file_writer.rb @@ -99,9 +99,7 @@ def self.open(file_name) # still be cut mid-character. def self.byteslice_at_char_boundary(string, max_bytesize) sliced = string.byteslice(0, max_bytesize) - if string.valid_encoding? - sliced = sliced.byteslice(0, sliced.bytesize - 1) until sliced.valid_encoding? - end + sliced.scrub!("") if string.valid_encoding? sliced end private_class_method :byteslice_at_char_boundary From f449acaa4971c555e33a31f90229491419543234 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 25 Aug 2026 12:55:46 +0900 Subject: [PATCH 2/3] Use FD-based operations Operations on an already open file are faster and safer than those based on the path name. --- lib/rubygems/util/atomic_file_writer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/util/atomic_file_writer.rb b/lib/rubygems/util/atomic_file_writer.rb index c3be873c9eba..6f75e38d51f8 100644 --- a/lib/rubygems/util/atomic_file_writer.rb +++ b/lib/rubygems/util/atomic_file_writer.rb @@ -53,9 +53,9 @@ def self.open(file_name) if old_stat # Set correct permissions on new file begin - File.chown(old_stat.uid, old_stat.gid, tmp_path) + temp_file.chown(old_stat.uid, old_stat.gid) # This operation will affect filesystem ACL's - File.chmod(old_stat.mode, tmp_path) + temp_file.chmod(old_stat.mode) rescue Errno::EPERM, Errno::EACCES # Changing file ownership failed, moving on. end From 5e1eb084d696e66058155cc19b54ca25b13cb225 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 3 Sep 2026 17:05:43 +0900 Subject: [PATCH 3/3] Keep trimming the tail instead of String#scrub! A UTF-8 replacement makes String#scrub! raise Encoding::CompatibilityError on an ASCII-incompatible receiver such as UTF-16LE, where the loop trimmed the tail fine. It is also slower than the loop for the common case of an ASCII name that needs no truncation. Co-Authored-By: Claude Opus 5 --- lib/rubygems/util/atomic_file_writer.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/rubygems/util/atomic_file_writer.rb b/lib/rubygems/util/atomic_file_writer.rb index 6f75e38d51f8..a8eadcb6498b 100644 --- a/lib/rubygems/util/atomic_file_writer.rb +++ b/lib/rubygems/util/atomic_file_writer.rb @@ -99,7 +99,9 @@ def self.open(file_name) # still be cut mid-character. def self.byteslice_at_char_boundary(string, max_bytesize) sliced = string.byteslice(0, max_bytesize) - sliced.scrub!("") if string.valid_encoding? + if string.valid_encoding? + sliced = sliced.byteslice(0, sliced.bytesize - 1) until sliced.valid_encoding? + end sliced end private_class_method :byteslice_at_char_boundary