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/