ruby-changes:50003
From: nobu <ko1@a...>
Date: Wed, 31 Jan 2018 13:25:03 +0900 (JST)
Subject: [ruby-changes:50003] nobu:r62121 (trunk): io.c: pipe_register_fptr
nobu 2018-01-31 13:24:57 +0900 (Wed, 31 Jan 2018) New Revision: 62121 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62121 Log: io.c: pipe_register_fptr * io.c (pipe_register_fptr): get rid of double registration which causes access after free and segfault. Modified files: trunk/io.c trunk/test/ruby/test_process.rb Index: test/ruby/test_process.rb =================================================================== --- test/ruby/test_process.rb (revision 62120) +++ test/ruby/test_process.rb (revision 62121) @@ -1810,6 +1810,15 @@ class TestProcess < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_process.rb#L1810 end end + def test_popen_reopen + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + io = File.open(IO::NULL) + IO.popen("echo") {|f| io.reopen(f)} + io.reopen(io.dup) + end; + end + def test_execopts_new_pgroup return unless windows? Index: io.c =================================================================== --- io.c (revision 62120) +++ io.c (revision 62121) @@ -6194,6 +6194,20 @@ pipe_finalize(rb_io_t *fptr, int noraise https://github.com/ruby/ruby/blob/trunk/io.c#L6194 #endif pipe_del_fptr(fptr); } + +static void +pipe_register_fptr(rb_io_t *fptr) +{ + struct pipe_list *list; + + if (fptr->finalize != pipe_finalize) return; + + for (list = pipe_list; list; list = list->next) { + if (list->fptr == fptr) return; + } + + pipe_add_fptr(fptr); +} #endif void @@ -7146,8 +7160,7 @@ io_reopen(VALUE io, VALUE nfile) https://github.com/ruby/ruby/blob/trunk/io.c#L7160 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil; fptr->finalize = orig->finalize; #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK) - if (fptr->finalize == pipe_finalize) - pipe_add_fptr(fptr); + pipe_register_fptr(fptr); #endif fd = fptr->fd; @@ -7329,8 +7342,7 @@ rb_io_init_copy(VALUE dest, VALUE io) https://github.com/ruby/ruby/blob/trunk/io.c#L7342 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv; fptr->finalize = orig->finalize; #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK) - if (fptr->finalize == pipe_finalize) - pipe_add_fptr(fptr); + pipe_register_fptr(fptr); #endif fd = ruby_dup(orig->fd); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/