[前][次][番号順一覧][スレッド一覧]

ruby-changes:50005

From: nobu <ko1@a...>
Date: Wed, 31 Jan 2018 17:17:22 +0900 (JST)
Subject: [ruby-changes:50005] nobu:r62123 (trunk): io.c: fptr_copy_finalizer

nobu	2018-01-31 17:17:16 +0900 (Wed, 31 Jan 2018)

  New Revision: 62123

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62123

  Log:
    io.c: fptr_copy_finalizer
    
    * io.c (fptr_copy_finalizer): remove fptr from pipe_list when pipe
      became ordinary file, to fix access after free.  to be finalized
      by pipe_finalize and being in pipe_list must match.

  Modified files:
    trunk/io.c
    trunk/test/ruby/test_process.rb
Index: io.c
===================================================================
--- io.c	(revision 62122)
+++ io.c	(revision 62123)
@@ -6194,21 +6194,30 @@ pipe_finalize(rb_io_t *fptr, int noraise https://github.com/ruby/ruby/blob/trunk/io.c#L6194
 #endif
     pipe_del_fptr(fptr);
 }
+#endif
 
 static void
-pipe_register_fptr(rb_io_t *fptr)
+fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
 {
-    struct pipe_list *list;
+#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
+    void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
+#endif
 
-    if (fptr->finalize != pipe_finalize) return;
+    fptr->finalize = orig->finalize;
 
-    for (list = pipe_list; list; list = list->next) {
-	if (list->fptr == fptr) return;
+#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
+    if (old_finalize == pipe_finalize) {
+	struct pipe_list *list;
+	for (list = pipe_list; list; list = list->next) {
+	    if (list->fptr == fptr) break;
+	}
+	if (!list) pipe_add_fptr(fptr);
+    }
+    else {
+	pipe_del_fptr(fptr);
     }
-
-    pipe_add_fptr(fptr);
-}
 #endif
+}
 
 void
 rb_io_synchronized(rb_io_t *fptr)
@@ -7158,10 +7167,7 @@ io_reopen(VALUE io, VALUE nfile) https://github.com/ruby/ruby/blob/trunk/io.c#L7167
     fptr->lineno = orig->lineno;
     if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
     else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
-    fptr->finalize = orig->finalize;
-#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
-    pipe_register_fptr(fptr);
-#endif
+    fptr_copy_finalizer(fptr, orig);
 
     fd = fptr->fd;
     fd2 = orig->fd;
@@ -7340,10 +7346,7 @@ rb_io_init_copy(VALUE dest, VALUE io) https://github.com/ruby/ruby/blob/trunk/io.c#L7346
     fptr->pid = orig->pid;
     fptr->lineno = orig->lineno;
     if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
-    fptr->finalize = orig->finalize;
-#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
-    pipe_register_fptr(fptr);
-#endif
+    fptr_copy_finalizer(fptr, orig);
 
     fd = ruby_dup(orig->fd);
     fptr->fd = fd;
Index: test/ruby/test_process.rb
===================================================================
--- test/ruby/test_process.rb	(revision 62122)
+++ test/ruby/test_process.rb	(revision 62123)
@@ -1814,8 +1814,9 @@ class TestProcess < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_process.rb#L1814
     assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
     begin;
       io = File.open(IO::NULL)
+      io2 = io.dup
       IO.popen("echo") {|f| io.reopen(f)}
-      io.reopen(io.dup)
+      io.reopen(io2)
     end;
   end
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]