Bug #22342
closedIO#gets can ignore the limit argument in some edge cases
Description
io.gets(rs, limit) ignores the limit value and reads until rs is found or EOF, if the limit-th byte of the stream matches rs's last byte and:
- The potential start of the record separator, the
limit-rs.bytesize-th byte of the stream is not at a character boundary
str = "\x83\\xxx".force_encoding("Windows-31J") # "ソxxx".encode("Windows-31J")
IO.pipe("Windows-31J"){|r,w|w.write(str); w.close_write; p r.gets("\\", 2); p r.read}
# Expected:
"\x{835C}"
"xxx"
# Actual:
"\x{835C}xxx"
""
- Or,
limit < rs.bytesize
IO.pipe{|r,w|w.write("a:bc"); w.close_write; p r.gets(":::", 2); p r.read}
# Expected:
"a:"
"bc"
# Actual:
"a:bc"
""
This behavior appears to date back to Ruby 1.9.x.
Updated by rhenium (Kazuki Yamaguchi) 5 days ago
I've opened a GitHub PR for this: https://github.com/ruby/ruby/pull/18961
Updated by rhenium (Kazuki Yamaguchi) 1 day ago
- Status changed from Open to Closed
Applied in changeset git|227006291d35b2255b3f7a888d75102c129b0472.
Fix IO#gets ignoring the limit argument
IO#gets first searches for separator candidates by looking for the last
byte of the record separator, and then checks whether it is an actual
match.
If a candidate is found at limit-th byte of the stream but is rejected
because it does not start at a character boundary, the limit check is
incorrectly skipped.
[Bug #22342]
Updated by nagachika (Tomoyuki Chikanaga) 1 day ago
- Backport changed from 3.3: UNKNOWN, 3.4: REQUIRED, 4.0: REQUIRED to 3.3: UNKNOWN, 3.4: DONE, 4.0: REQUIRED
ruby_3_4 0a33ab92c08c8d1dbba0b3c97781d16b40ac53a8 merged revision(s) 227006291d35b2255b3f7a888d75102c129b0472.