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

[ruby/stringio] Fix each with multiple character string and chomp

Previously, this could result in an infinite loop.  Always update
the e pointer in this case, setting w when chomping so the chomped
data is not included in the output.

Fixes [Bug #18769]

https://github.com/ruby/stringio/commit/4bf64d5130
This commit is contained in:
Jeremy Evans 2022-05-26 15:22:28 -07:00 committed by git
parent bb6357cddd
commit 1f82269f4e
2 changed files with 10 additions and 2 deletions

View file

@ -1181,7 +1181,7 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
const char *s, *e, *p; const char *s, *e, *p;
long n, limit = arg->limit; long n, limit = arg->limit;
VALUE str = arg->rs; VALUE str = arg->rs;
int w = 0; long w = 0;
rb_encoding *enc = get_enc(ptr); rb_encoding *enc = get_enc(ptr);
if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) { if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
@ -1237,7 +1237,8 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
if (e - s < 1024) { if (e - s < 1024) {
for (p = s; p + n <= e; ++p) { for (p = s; p + n <= e; ++p) {
if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) { if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
e = p + (arg->chomp ? 0 : n); e = p + n;
w = (arg->chomp ? n : 0);
break; break;
} }
} }

View file

@ -584,6 +584,13 @@ class TestStringIO < Test::Unit::TestCase
end end
end end
def test_each_string_sep
f = StringIO.new('a||b||c')
assert_equal(["a||", "b||", "c"], f.each("||").to_a)
f.rewind
assert_equal(["a", "b", "c"], f.each("||", chomp: true).to_a)
end
def test_each def test_each
f = StringIO.new("foo\nbar\nbaz\n") f = StringIO.new("foo\nbar\nbaz\n")
assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a) assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a)