`rb_io_puts` should not write zero length strings. (#7806)

This commit is contained in:
Samuel Williams 2023-05-15 11:13:51 +09:00 коммит произвёл GitHub
Родитель 91c004885f
Коммит 0b2613f443
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 52 добавлений и 16 удалений

40
io.c
Просмотреть файл

@ -1327,14 +1327,15 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
static ssize_t
rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
{
if (!iovcnt) return 0;
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
for (int i = 0; i < iovcnt; i += 1) {
VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[i].iov_base, iov[i].iov_len, 0);
// This path assumes at least one `iov`:
VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[0].iov_base, iov[0].iov_len, 0);
if (!UNDEF_P(result)) {
return rb_fiber_scheduler_io_result_apply(result);
}
if (!UNDEF_P(result)) {
return rb_fiber_scheduler_io_result_apply(result);
}
}
@ -2041,7 +2042,7 @@ io_binwritev_internal(VALUE arg)
while (remaining) {
long result = rb_writev_internal(fptr, iov, iovcnt);
if (result > 0) {
if (result >= 0) {
offset += result;
if (fptr->wbuf.ptr && fptr->wbuf.len) {
if (offset < (size_t)fptr->wbuf.len) {
@ -8914,7 +8915,6 @@ io_puts_ary(VALUE ary, VALUE out, int recur)
VALUE
rb_io_puts(int argc, const VALUE *argv, VALUE out)
{
int i, n;
VALUE line, args[2];
/* if no argument given, print newline. */
@ -8922,22 +8922,30 @@ rb_io_puts(int argc, const VALUE *argv, VALUE out)
rb_io_write(out, rb_default_rs);
return Qnil;
}
for (i=0; i<argc; i++) {
for (int i = 0; i < argc; i++) {
// Convert the argument to a string:
if (RB_TYPE_P(argv[i], T_STRING)) {
line = argv[i];
goto string;
}
if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
continue;
}
line = rb_obj_as_string(argv[i]);
string:
n = 0;
args[n++] = line;
if (RSTRING_LEN(line) == 0 ||
!rb_str_end_with_asciichar(line, '\n')) {
else {
line = rb_obj_as_string(argv[i]);
}
// Write the line:
int n = 0;
if (RSTRING_LEN(line) == 0) {
args[n++] = rb_default_rs;
}
else {
args[n++] = line;
if (!rb_str_end_with_asciichar(line, '\n')) {
args[n++] = rb_default_rs;
}
}
rb_io_writev(out, n, args);
}

Просмотреть файл

@ -170,6 +170,34 @@ class TestFiberIO < Test::Unit::TestCase
assert_predicate(o, :closed?)
end
def test_puts_empty
omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
i, o = UNIXSocket.pair
i.nonblock = false
o.nonblock = false
thread = Thread.new do
# This scheduler provides non-blocking `io_read`/`io_write`:
scheduler = IOBufferScheduler.new
Fiber.set_scheduler scheduler
Fiber.schedule do
# This was causing a segfault on older Ruby.
o.puts ""
o.puts nil
o.close
end
end
thread.join
message = i.read
i.close
assert_equal $/*2, message
end
def test_io_select
omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)