1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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]
This commit is contained in:
Jeremy Evans 2021-02-09 13:50:36 -08:00 committed by Nobuyoshi Nakada
parent efd19badf4
commit cfd162d535
Notes: git 2021-02-20 11:18:14 +09:00
4 changed files with 40 additions and 20 deletions

View file

@ -7,11 +7,13 @@ describe "String#lstrip" do
" hello world ".lstrip.should == "hello world " " hello world ".lstrip.should == "hello world "
"\n\r\t\n\v\r hello world ".lstrip.should == "hello world " "\n\r\t\n\v\r hello world ".lstrip.should == "hello world "
"hello".lstrip.should == "hello" "hello".lstrip.should == "hello"
"\000 \000hello\000 \000".lstrip.should == "\000 \000hello\000 \000"
end end
it "does not strip leading \\0" do ruby_version_is '3.1' do
"\x00hello".lstrip.should == "\x00hello" it "strips leading \\0" do
"\x00hello".lstrip.should == "hello"
"\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
end
end end
ruby_version_is ''...'2.7' do ruby_version_is ''...'2.7' do
@ -28,10 +30,14 @@ describe "String#lstrip!" do
a = " hello " a = " hello "
a.lstrip!.should equal(a) a.lstrip!.should equal(a)
a.should == "hello " a.should == "hello "
end
a = "\000 \000hello\000 \000" ruby_version_is '3.1' do
a.lstrip! it "strips leading \\0" do
a.should == "\000 \000hello\000 \000" a = "\000 \000hello\000 \000"
a.lstrip!
a.should == "hello\000 \000"
end
end end
it "returns nil if no modifications were made" do it "returns nil if no modifications were made" do

View file

@ -6,11 +6,12 @@ describe "String#strip" do
" hello ".strip.should == "hello" " hello ".strip.should == "hello"
" hello world ".strip.should == "hello world" " hello world ".strip.should == "hello world"
"\tgoodbye\r\v\n".strip.should == "goodbye" "\tgoodbye\r\v\n".strip.should == "goodbye"
"\x00 goodbye \x00".strip.should == "\x00 goodbye"
end end
it "returns a copy of self with trailing NULL bytes and whitespace" do ruby_version_is '3.1' do
" \x00 goodbye \x00 ".strip.should == "\x00 goodbye" it "returns a copy of self without leading and trailing NULL bytes and whitespace" do
" \x00 goodbye \x00 ".strip.should == "goodbye"
end
end end
ruby_version_is ''...'2.7' do ruby_version_is ''...'2.7' do
@ -31,11 +32,6 @@ describe "String#strip!" do
a = "\tgoodbye\r\v\n" a = "\tgoodbye\r\v\n"
a.strip! a.strip!
a.should == "goodbye" a.should == "goodbye"
a = "\000 goodbye \000"
a.strip!
a.should == "\000 goodbye"
end end
it "returns nil if no modifications where made" do it "returns nil if no modifications where made" do
@ -44,10 +40,12 @@ describe "String#strip!" do
a.should == "hello" a.should == "hello"
end end
it "modifies self removing trailing NULL bytes and whitespace" do ruby_version_is '3.1' do
a = " \x00 goodbye \x00 " it "removes leading and trailing NULL bytes and whitespace" do
a.strip! a = "\000 goodbye \000"
a.should == "\x00 goodbye" a.strip!
a.should == "goodbye"
end
end end
it "raises a FrozenError on a frozen instance that is modified" do it "raises a FrozenError on a frozen instance that is modified" do

View file

@ -9263,14 +9263,14 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
/* remove spaces at head */ /* remove spaces at head */
if (single_byte_optimizable(str)) { if (single_byte_optimizable(str)) {
while (s < e && ascii_isspace(*s)) s++; while (s < e && (*s == '\0' || ascii_isspace(*s))) s++;
} }
else { else {
while (s < e) { while (s < e) {
int n; int n;
unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc); unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
if (!rb_isspace(cc)) break; if (cc && !rb_isspace(cc)) break;
s += n; s += n;
} }
} }

View file

@ -1852,6 +1852,7 @@ CODE
def test_strip def test_strip
assert_equal(S("x"), S(" x ").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(" \n\r\t x \t\r\n\n ").strip)
assert_equal(S("x"), S("\x00x\x00").strip)
assert_equal("0b0 ".force_encoding("UTF-16BE"), assert_equal("0b0 ".force_encoding("UTF-16BE"),
"\x00 0b0 ".force_encoding("UTF-16BE").strip) "\x00 0b0 ".force_encoding("UTF-16BE").strip)
@ -1870,6 +1871,10 @@ CODE
assert_equal(S("x"), a.strip!) assert_equal(S("x"), a.strip!)
assert_equal(S("x"), a) assert_equal(S("x"), a)
a = S("\x00x\x00")
assert_equal(S("x"), a.strip!)
assert_equal(S("x"), a)
a = S("x") a = S("x")
assert_nil(a.strip!) assert_nil(a.strip!)
assert_equal(S("x") ,a) assert_equal(S("x") ,a)
@ -2703,6 +2708,7 @@ CODE
def test_rstrip def test_rstrip
assert_equal(" hello", " hello ".rstrip) assert_equal(" hello", " hello ".rstrip)
assert_equal("\u3042", "\u3042 ".rstrip) assert_equal("\u3042", "\u3042 ".rstrip)
assert_equal("\u3042", "\u3042\u0000".rstrip)
assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip } assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip }
end end
@ -2723,12 +2729,17 @@ CODE
assert_equal(nil, s4.rstrip!) assert_equal(nil, s4.rstrip!)
assert_equal("\u3042", s4) 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! } assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! }
end end
def test_lstrip def test_lstrip
assert_equal("hello ", " hello ".lstrip) assert_equal("hello ", " hello ".lstrip)
assert_equal("\u3042", " \u3042".lstrip) assert_equal("\u3042", " \u3042".lstrip)
assert_equal("hello ", "\x00hello ".lstrip)
end end
def test_lstrip_bang def test_lstrip_bang
@ -2747,6 +2758,11 @@ CODE
s4 = S("\u3042") s4 = S("\u3042")
assert_equal(nil, s4.lstrip!) assert_equal(nil, s4.lstrip!)
assert_equal("\u3042", s4) assert_equal("\u3042", s4)
s5 = S("\u0000\u3042")
assert_equal("\u3042", s5.lstrip!)
assert_equal("\u3042", s5)
end end
def test_delete_prefix def test_delete_prefix