Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions ext/stringio/stringio.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,18 @@ check_modifiable(struct StringIO *ptr)
}
}

static inline bool
outside_p(struct StringIO *ptr, long pos)
{
return NIL_P(ptr->string) || pos >= RSTRING_LEN(ptr->string);
}

static inline bool
eos_p(struct StringIO *ptr)
{
return outside_p(ptr, ptr->pos);
}

static VALUE
strio_s_allocate(VALUE klass)
{
Expand Down Expand Up @@ -628,9 +640,8 @@ static struct StringIO *
strio_to_read(VALUE self)
{
struct StringIO *ptr = readable(self);
if (NIL_P(ptr->string)) return NULL;
if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
return NULL;
if (eos_p(ptr)) return NULL;
return ptr;
}

/*
Expand Down Expand Up @@ -837,7 +848,11 @@ strio_seek(int argc, VALUE *argv, VALUE self)
offset = ptr->pos;
break;
case 2:
offset = RSTRING_LEN(ptr->string);
if (NIL_P(ptr->string)) {
offset = 0;
} else {
offset = RSTRING_LEN(ptr->string);
}
break;
default:
error_inval("invalid whence");
Expand Down Expand Up @@ -906,7 +921,7 @@ strio_getc(VALUE self)
int len;
char *p;

if (NIL_P(str) || pos >= RSTRING_LEN(str)) {
if (eos_p(ptr)) {
return Qnil;
}
p = RSTRING_PTR(str)+pos;
Expand All @@ -927,7 +942,7 @@ strio_getbyte(VALUE self)
{
struct StringIO *ptr = readable(self);
int c;
if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
if (eos_p(ptr)) {
return Qnil;
}
c = RSTRING_PTR(ptr->string)[ptr->pos++];
Expand Down Expand Up @@ -1605,10 +1620,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
if (len > 0 &&
(NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
if (eos_p(ptr)) {
if (!NIL_P(str)) rb_str_resize(str, 0);
return Qnil;
return len > 0 ? Qnil : rb_str_new(0, 0);
}
binary = 1;
break;
Expand Down Expand Up @@ -1684,7 +1698,7 @@ strio_pread(int argc, VALUE *argv, VALUE self)

struct StringIO *ptr = readable(self);

if (offset >= RSTRING_LEN(ptr->string)) {
if (outside_p(ptr, offset)) {
rb_eof_error();
}

Expand Down Expand Up @@ -1921,7 +1935,7 @@ Init_stringio(void)
#undef rb_intern

#ifdef HAVE_RB_EXT_RACTOR_SAFE
rb_ext_ractor_safe(true);
rb_ext_ractor_safe(true);
#endif

VALUE StringIO = rb_define_class("StringIO", rb_cObject);
Expand Down
25 changes: 25 additions & 0 deletions test/stringio/test_stringio.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,31 @@ def test_null
assert_nil io.getc
end

def test_pread_eof
io = StringIO.new(nil)
assert_predicate io, :eof?
end

def test_pread_null
io = StringIO.new(nil)
assert_raise(EOFError) { io.pread(1, 0) }
end

def test_read_null
io = StringIO.new(nil)
assert_equal "", io.read(0)
end

def test_seek_null
io = StringIO.new(nil)
assert_equal(0, io.seek(0, IO::SEEK_SET))
assert_equal(0, io.pos)
assert_equal(0, io.seek(0, IO::SEEK_CUR))
assert_equal(0, io.pos)
assert_equal(0, io.seek(0, IO::SEEK_END)) # This should not segfault
assert_equal(0, io.pos)
end

def test_truncate
io = StringIO.new("")
io.puts "abc"
Expand Down
4 changes: 2 additions & 2 deletions time.c
Original file line number Diff line number Diff line change
Expand Up @@ -1891,8 +1891,8 @@ static void
time_mark_and_move(void *ptr)
{
struct time_object *tobj = ptr;
if (!FIXWV_P(tobj->timew)) {
rb_gc_mark_and_move(&WIDEVAL_GET(tobj->timew));
if (!WIDEVALUE_IS_WIDER || !FIXWV_P(tobj->timew)) {
rb_gc_mark_and_move((VALUE *)&WIDEVAL_GET(tobj->timew));
}
rb_gc_mark_and_move(&tobj->vtm.year);
rb_gc_mark_and_move(&tobj->vtm.subsecx);
Expand Down