From e5825de7c9f07e4f7bd2b83ce8973e19a4652916 Mon Sep 17 00:00:00 2001 From: alexandre184 <110398901+alexandre184@users.noreply.github.com> Date: Sat, 15 Jul 2023 09:36:53 +0200 Subject: [PATCH] [Bug #19769] Fix range of size 1 in `String#tr` --- spec/ruby/core/string/tr_s_spec.rb | 9 +++++++++ spec/ruby/core/string/tr_spec.rb | 9 +++++++++ string.c | 6 ++++-- test/ruby/test_string.rb | 8 ++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/spec/ruby/core/string/tr_s_spec.rb b/spec/ruby/core/string/tr_s_spec.rb index b5c87d4e4e..3c31473044 100644 --- a/spec/ruby/core/string/tr_s_spec.rb +++ b/spec/ruby/core/string/tr_s_spec.rb @@ -17,6 +17,15 @@ describe "String#tr_s" do "hello ^--^".tr_s("---", "_").should == "hello ^_^" end + ruby_bug "#19769", ""..."3.3" do + it "accepts c1-c1 notation to denote range of one character" do + "hello".tr_s('e-e', 'x').should == "hxllo" + "123456789".tr_s("2-23","xy").should == "1xy456789" + "hello ^-^".tr_s("e-", "a-a_").should == "hallo ^_^" + "hello ^-^".tr_s("---o", "_a").should == "hella ^_^" + end + end + it "pads to_str with its last char if it is shorter than from_string" do "this".tr_s("this", "x").should == "x" end diff --git a/spec/ruby/core/string/tr_spec.rb b/spec/ruby/core/string/tr_spec.rb index cf485d32a3..d60480dc7e 100644 --- a/spec/ruby/core/string/tr_spec.rb +++ b/spec/ruby/core/string/tr_spec.rb @@ -16,6 +16,15 @@ describe "String#tr" do "hello ^-^".tr("---", "_").should == "hello ^_^" end + ruby_bug "#19769", ""..."3.3" do + it "accepts c1-c1 notation to denote range of one character" do + "hello".tr('e-e', 'x').should == "hxllo" + "123456789".tr("2-23","xy").should == "1xy456789" + "hello ^-^".tr("e-", "a-a_").should == "hallo ^_^" + "hello ^-^".tr("---o", "_a").should == "hella ^_^" + end + end + it "pads to_str with its last char if it is shorter than from_string" do "this".tr("this", "x").should == "xxxx" "hello".tr("a-z", "A-H.").should == "HE..." diff --git a/string.c b/string.c index af0668e4b2..9cc4dfd3ce 100644 --- a/string.c +++ b/string.c @@ -7714,8 +7714,10 @@ trnext(struct tr *t, rb_encoding *enc) } continue; /* not reached */ } - t->gen = 1; - t->max = c; + else if (t->now < c) { + t->gen = 1; + t->max = c; + } } } return t->now; diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 06df67de38..6cc958332f 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -2301,6 +2301,8 @@ CODE assert_not_predicate(str, :ascii_only?) assert_not_predicate(star, :ascii_only?) assert_not_predicate(result, :ascii_only?, bug13950) + + assert_equal(S("XYC"), S("ABC").tr("A-AB", "XY")) end def test_tr! @@ -2325,6 +2327,8 @@ CODE a = S("abc".force_encoding(Encoding::US_ASCII)) assert_nil(a.tr!(S("z"), S("\u0101")), '[ruby-core:22326]') assert_equal(Encoding::US_ASCII, a.encoding, '[ruby-core:22326]') + + assert_equal(S("XYC"), S("ABC").tr!("A-AB", "XY")) end def test_tr_s @@ -2332,6 +2336,8 @@ CODE assert_equal(S("h*o"), S("hello").tr_s(S("el"), S("*"))) assert_equal("a".hash, S("\u0101\u0101").tr_s("\u0101", "a").hash) assert_equal(true, S("\u3041\u3041").tr("\u3041", "a").ascii_only?) + + assert_equal(S("XYC"), S("ABC").tr_s("A-AB", "XY")) end def test_tr_s! @@ -2344,6 +2350,8 @@ CODE a = S("hello") assert_equal(S("h*o"), a.tr_s!(S("el"), S("*"))) assert_equal(S("h*o"), a) + + assert_equal(S("XYC"), S("ABC").tr_s!("A-AB", "XY")) end def test_unpack