From adf6874cd1e6765a693d187a89fd6ec64f422d5a Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Thu, 27 Aug 2026 23:36:00 +0300 Subject: [PATCH 1/2] Serialize FTP typecodes without mutating the URI --- lib/uri/ftp.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/uri/ftp.rb b/lib/uri/ftp.rb index 1c75e24..0270af5 100644 --- a/lib/uri/ftp.rb +++ b/lib/uri/ftp.rb @@ -249,14 +249,11 @@ def set_path(v) # Returns a String representation of the URI::FTP. def to_s - save_path = nil - if @typecode - save_path = @path - @path = @path + TYPECODE_PREFIX + @typecode - end str = super if @typecode - @path = save_path + suffix_length = (@query ? @query.length + 1 : 0) + + (@fragment ? @fragment.length + 1 : 0) + str.insert(-suffix_length - 1, TYPECODE_PREFIX + @typecode) end return str From 90e45569db16358c269f0532754afb80ed84d7ed Mon Sep 17 00:00:00 2001 From: Oskar Eichler <62393985+OskarEichler@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:03:56 +0300 Subject: [PATCH 2/2] test: cover URI regression --- test/uri/test_ftp.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/uri/test_ftp.rb b/test/uri/test_ftp.rb index 3ad7864..d35f209 100644 --- a/test/uri/test_ftp.rb +++ b/test/uri/test_ftp.rb @@ -6,6 +6,15 @@ class URI::TestFTP < Test::Unit::TestCase def setup end + + def test_to_s_does_not_mutate_frozen_ftp_uri + uri = URI.parse("ftp://example.test/file;type=i?download=1#section").freeze + + 2.times do + assert_equal("ftp://example.test/file;type=i?download=1#section", uri.to_s) + end + end + def test_parse url = URI.parse('ftp://user:pass@host.com/abc/def') assert_kind_of(URI::FTP, url)