aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-01-30 22:03:57 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-01-30 22:03:57 +0000
commit345c459abfcab0d9f50468ad49a5bc3087b2381e (patch)
tree1f57203b2233d5b8ea6852d0cbbf9a417d7a47df /io.c
parent88bd76c7990e14f8ca6dc1055e1d17258620ba6b (diff)
downloadruby-345c459abfcab0d9f50468ad49a5bc3087b2381e.tar.gz
io.c (rb_io_syswrite): avoid leaving garbage after write
As with IO#write, IO#syswrite also generates garbage which can be harmful in hand-coded read-write loops. * io.c (swrite_arg, swrite_do, swrite_end): new (rb_io_syswrite): use new functions to cleanup garbage [ruby-core:78898] [Bug #13085] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57472 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/io.c b/io.c
index d03519be92..57ad592daf 100644
--- a/io.c
+++ b/io.c
@@ -4745,6 +4745,34 @@ rb_io_sysseek(int argc, VALUE *argv, VALUE io)
return OFFT2NUM(pos);
}
+struct swrite_arg {
+ VALUE orig;
+ VALUE tmp;
+ rb_io_t *fptr;
+};
+
+static VALUE
+swrite_do(VALUE arg)
+{
+ struct swrite_arg *sa = (struct swrite_arg *)arg;
+ const char *ptr;
+ long len;
+
+ RSTRING_GETMEM(sa->tmp, ptr, len);
+
+ return (VALUE)rb_write_internal(sa->fptr->fd, ptr, len);
+}
+
+static VALUE
+swrite_end(VALUE arg)
+{
+ struct swrite_arg *sa = (struct swrite_arg *)arg;
+
+ rb_str_tmp_frozen_release(sa->orig, sa->tmp);
+
+ return Qfalse;
+}
+
/*
* call-seq:
* ios.syswrite(string) -> integer
@@ -4761,26 +4789,25 @@ rb_io_sysseek(int argc, VALUE *argv, VALUE io)
static VALUE
rb_io_syswrite(VALUE io, VALUE str)
{
- rb_io_t *fptr;
+ struct swrite_arg sa;
long n;
if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
io = GetWriteIO(io);
- GetOpenFile(io, fptr);
- rb_io_check_writable(fptr);
-
- str = rb_str_new_frozen(str);
+ GetOpenFile(io, sa.fptr);
+ rb_io_check_writable(sa.fptr);
- if (fptr->wbuf.len) {
+ if (sa.fptr->wbuf.len) {
rb_warn("syswrite for buffered IO");
}
- n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
- RB_GC_GUARD(str);
+ sa.orig = str;
+ sa.tmp = rb_str_tmp_frozen_acquire(str);
+ n = (long)rb_ensure(swrite_do, (VALUE)&sa, swrite_end, (VALUE)&sa);
- if (n == -1) rb_sys_fail_path(fptr->pathv);
+ if (n == -1) rb_sys_fail_path(sa.fptr->pathv);
return LONG2FIX(n);
}