Skip to content

Commit 1ed61d0

Browse files
committed
Check if closed in loop
[Bug #17675] https://bugs.ruby-lang.org/issues/17675
1 parent 52b0245 commit 1ed61d0

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

ext/stringio/stringio.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* -*- mode: c; indent-tabs-mode: t -*- */
12
/**********************************************************************
23
34
stringio.c -
@@ -599,6 +600,14 @@ strio_closed_write(VALUE self)
599600
return Qtrue;
600601
}
601602

603+
static struct StringIO *
604+
strio_to_read(VALUE self)
605+
{
606+
struct StringIO *ptr = readable(self);
607+
if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
608+
return NULL;
609+
}
610+
602611
/*
603612
* call-seq:
604613
* strio.eof -> true or false
@@ -610,8 +619,7 @@ strio_closed_write(VALUE self)
610619
static VALUE
611620
strio_eof(VALUE self)
612621
{
613-
struct StringIO *ptr = readable(self);
614-
if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
622+
if (strio_to_read(self)) return Qfalse;
615623
return Qtrue;
616624
}
617625

@@ -821,11 +829,11 @@ strio_get_sync(VALUE self)
821829
static VALUE
822830
strio_each_byte(VALUE self)
823831
{
824-
struct StringIO *ptr = readable(self);
832+
struct StringIO *ptr;
825833

826834
RETURN_ENUMERATOR(self, 0, 0);
827835

828-
while (ptr->pos < RSTRING_LEN(ptr->string)) {
836+
while ((ptr = strio_to_read(self)) != NULL) {
829837
char c = RSTRING_PTR(ptr->string)[ptr->pos++];
830838
rb_yield(CHR2FIX(c));
831839
}
@@ -1064,11 +1072,7 @@ strio_each_codepoint(VALUE self)
10641072

10651073
ptr = readable(self);
10661074
enc = get_enc(ptr);
1067-
for (;;) {
1068-
if (ptr->pos >= RSTRING_LEN(ptr->string)) {
1069-
return self;
1070-
}
1071-
1075+
while ((ptr = strio_to_read(self)) != NULL) {
10721076
c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
10731077
RSTRING_END(ptr->string), &n, enc);
10741078
ptr->pos += n;

test/stringio/test_stringio.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,15 @@ def test_each_byte
446446
f.close unless f.closed?
447447
end
448448

449+
def test_each_byte_closed
450+
f = StringIO.new("1234")
451+
assert_equal("1".ord, f.each_byte {|c| f.close; break c })
452+
f = StringIO.new("1234")
453+
assert_raise(IOError) do
454+
f.each_byte { f.close }
455+
end
456+
end
457+
449458
def test_getbyte
450459
f = StringIO.new("1234")
451460
assert_equal("1".ord, f.getbyte)
@@ -520,11 +529,29 @@ def test_each_char
520529
assert_equal(%w(1 2 3 4), f.each_char.to_a)
521530
end
522531

532+
def test_each_char_closed
533+
f = StringIO.new("1234")
534+
assert_equal("1", f.each_char {|c| f.close; break c })
535+
f = StringIO.new("1234")
536+
assert_raise(IOError) do
537+
f.each_char { f.close }
538+
end
539+
end
540+
523541
def test_each_codepoint
524542
f = StringIO.new("1234")
525543
assert_equal([49, 50, 51, 52], f.each_codepoint.to_a)
526544
end
527545

546+
def test_each_codepoint_closed
547+
f = StringIO.new("1234")
548+
assert_equal("1".ord, f.each_codepoint {|c| f.close; break c })
549+
f = StringIO.new("1234")
550+
assert_raise(IOError) do
551+
f.each_codepoint { f.close }
552+
end
553+
end
554+
528555
def test_each_codepoint_enumerator
529556
io = StringIO.new('你好построить')
530557

0 commit comments

Comments
 (0)