diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-31 08:17:16 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-31 08:17:16 +0000 |
commit | 4057ee5e8e054f3487a084d338f93cee9420c7eb (patch) | |
tree | 554e4a5291a61316d3eec6bf8affe9d226e451f5 | |
parent | 302825ced8450d0e9b1d2d8458e1748a917459bc (diff) |
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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62123 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | io.c | 35 | ||||
-rw-r--r-- | test/ruby/test_process.rb | 3 |
2 files changed, 21 insertions, 17 deletions
@@ -6194,21 +6194,30 @@ pipe_finalize(rb_io_t *fptr, int noraise) #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) 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) 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; diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 5d85ca3a18..0d2bc50b2d 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -1814,8 +1814,9 @@ class TestProcess < Test::Unit::TestCase 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 |