summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-02-09 13:50:36 -0800
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-02-20 11:17:47 +0900
commitcfd162d535c7a4f8b1f95255cc6be696a8b75557 (patch)
tree386d466aab972781cc6d1e35abd035bea506b65d
parentefd19badf43f4f1f24d5aec8a28e94a6e1e47b5b (diff)
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]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4164
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb18
-rw-r--r--spec/ruby/core/string/strip_spec.rb22
-rw-r--r--string.c4
-rw-r--r--test/ruby/test_string.rb16
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 12c7b13200..6b40189500 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
" 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
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 252d4a9cc3..463a9fedf3 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
" 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
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
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 dbff149840..7605c225b9 100644
--- a/string.c
+++ b/string.c
@@ -9263,14 +9263,14 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
/* 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 4814872789..29ad98beaf 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1852,6 +1852,7 @@ CODE
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
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
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
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
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