[前][次][番号順一覧][スレッド一覧]

ruby-changes:65300

From: Jeremy <ko1@a...>
Date: Sat, 20 Feb 2021 11:18:15 +0900 (JST)
Subject: [ruby-changes:65300] cfd162d535 (master): Make String#{strip, lstrip}{, !} strip leading NUL bytes

https://git.ruby-lang.org/ruby.git/commit/?id=cfd162d535

From cfd162d535c7a4f8b1f95255cc6be696a8b75557 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Tue, 9 Feb 2021 13:50:36 -0800
Subject: Make String#{strip,lstrip}{,!} strip leading NUL bytes

The documentation already specifies that they strip whitespace
and defines whitespace to include null.

This wraps the new behavior in the appropriate guards in the specs,
but does not specify behavior for previous versions, because this
is a bug that could be backported.

Fixes [Bug #17467]
---
 spec/ruby/core/string/lstrip_spec.rb | 18 ++++++++++++------
 spec/ruby/core/string/strip_spec.rb  | 22 ++++++++++------------
 string.c                             |  4 ++--
 test/ruby/test_string.rb             | 16 ++++++++++++++++
 4 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb
index 12c7b13..6b40189 100644
--- a/spec/ruby/core/string/lstrip_spec.rb
+++ b/spec/ruby/core/string/lstrip_spec.rb
@@ -7,11 +7,13 @@ describe "String#lstrip" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/string/lstrip_spec.rb#L7
    "  hello world  ".lstrip.should == "hello world  "
    "\n\r\t\n\v\r hello world  ".lstrip.should == "hello world  "
    "hello".lstrip.should == "hello"
-   "\000 \000hello\000 \000".lstrip.should == "\000 \000hello\000 \000"
   end
 
-  it "does not strip leading \\0" do
-   "\x00hello".lstrip.should == "\x00hello"
+  ruby_version_is '3.1' do
+    it "strips leading \\0" do
+     "\x00hello".lstrip.should == "hello"
+     "\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
+    end
   end
 
   ruby_version_is ''...'2.7' do
@@ -28,10 +30,14 @@ describe "String#lstrip!" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/string/lstrip_spec.rb#L30
     a = "  hello  "
     a.lstrip!.should equal(a)
     a.should == "hello  "
+  end
 
-    a = "\000 \000hello\000 \000"
-    a.lstrip!
-    a.should == "\000 \000hello\000 \000"
+  ruby_version_is '3.1' do
+    it "strips leading \\0" do
+      a = "\000 \000hello\000 \000"
+      a.lstrip!
+      a.should == "hello\000 \000"
+    end
   end
 
   it "returns nil if no modifications were made" do
diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb
index 252d4a9..463a9fe 100644
--- a/spec/ruby/core/string/strip_spec.rb
+++ b/spec/ruby/core/string/strip_spec.rb
@@ -6,11 +6,12 @@ describe "String#strip" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/string/strip_spec.rb#L6
     "   hello   ".strip.should == "hello"
     "   hello world   ".strip.should == "hello world"
     "\tgoodbye\r\v\n".strip.should == "goodbye"
-    "\x00 goodbye \x00".strip.should == "\x00 goodbye"
   end
 
-  it "returns a copy of self with trailing NULL bytes and whitespace" do
-    " \x00 goodbye \x00 ".strip.should == "\x00 goodbye"
+  ruby_version_is '3.1' do
+    it "returns a copy of self without leading and trailing NULL bytes and whitespace" do
+      " \x00 goodbye \x00 ".strip.should == "goodbye"
+    end
   end
 
   ruby_version_is ''...'2.7' do
@@ -31,11 +32,6 @@ describe "String#strip!" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/string/strip_spec.rb#L32
     a = "\tgoodbye\r\v\n"
     a.strip!
     a.should == "goodbye"
-
-    a = "\000 goodbye \000"
-    a.strip!
-    a.should == "\000 goodbye"
-
   end
 
   it "returns nil if no modifications where made" do
@@ -44,10 +40,12 @@ describe "String#strip!" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/string/strip_spec.rb#L40
     a.should == "hello"
   end
 
-  it "modifies self removing trailing NULL bytes and whitespace" do
-    a = " \x00 goodbye \x00 "
-    a.strip!
-    a.should == "\x00 goodbye"
+  ruby_version_is '3.1' do
+    it "removes leading and trailing NULL bytes and whitespace" do
+      a = "\000 goodbye \000"
+      a.strip!
+      a.should == "goodbye"
+    end
   end
 
   it "raises a FrozenError on a frozen instance that is modified" do
diff --git a/string.c b/string.c
index dbff149..7605c22 100644
--- a/string.c
+++ b/string.c
@@ -9263,14 +9263,14 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc) https://github.com/ruby/ruby/blob/trunk/string.c#L9263
 
     /* remove spaces at head */
     if (single_byte_optimizable(str)) {
-	while (s < e && ascii_isspace(*s)) s++;
+        while (s < e && (*s == '\0' || ascii_isspace(*s))) s++;
     }
     else {
 	while (s < e) {
 	    int n;
 	    unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
 
-	    if (!rb_isspace(cc)) break;
+            if (cc && !rb_isspace(cc)) break;
 	    s += n;
 	}
     }
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 4814872..29ad98b 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1852,6 +1852,7 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L1852
   def test_strip
     assert_equal(S("x"), S("      x        ").strip)
     assert_equal(S("x"), S(" \n\r\t     x  \t\r\n\n      ").strip)
+    assert_equal(S("x"), S("\x00x\x00").strip)
 
     assert_equal("0b0 ".force_encoding("UTF-16BE"),
                  "\x00 0b0 ".force_encoding("UTF-16BE").strip)
@@ -1870,6 +1871,10 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L1871
     assert_equal(S("x"), a.strip!)
     assert_equal(S("x"), a)
 
+    a = S("\x00x\x00")
+    assert_equal(S("x"), a.strip!)
+    assert_equal(S("x"), a)
+
     a = S("x")
     assert_nil(a.strip!)
     assert_equal(S("x") ,a)
@@ -2703,6 +2708,7 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L2708
   def test_rstrip
     assert_equal("  hello", "  hello  ".rstrip)
     assert_equal("\u3042", "\u3042   ".rstrip)
+    assert_equal("\u3042", "\u3042\u0000".rstrip)
     assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip }
   end
 
@@ -2723,12 +2729,17 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L2729
     assert_equal(nil, s4.rstrip!)
     assert_equal("\u3042", s4)
 
+    s5 = S("\u3042\u0000")
+    assert_equal("\u3042", s5.rstrip!)
+    assert_equal("\u3042", s5)
+
     assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! }
   end
 
   def test_lstrip
     assert_equal("hello  ", "  hello  ".lstrip)
     assert_equal("\u3042", "   \u3042".lstrip)
+    assert_equal("hello  ", "\x00hello  ".lstrip)
   end
 
   def test_lstrip_bang
@@ -2747,6 +2758,11 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L2758
     s4 = S("\u3042")
     assert_equal(nil, s4.lstrip!)
     assert_equal("\u3042", s4)
+
+    s5 = S("\u0000\u3042")
+    assert_equal("\u3042", s5.lstrip!)
+    assert_equal("\u3042", s5)
+
   end
 
   def test_delete_prefix
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]