To: vim_dev@googlegroups.com Subject: Patch 7.4.1828 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1828 Problem: May try to access buffer that's already freed. Solution: When freeing a buffer remove it from any channel. Files: src/buffer.c, src/channel.c, src/proto/channel.pro *** ../vim-7.4.1827/src/buffer.c 2016-03-19 22:11:47.412675093 +0100 --- src/buffer.c 2016-05-09 20:30:02.966071124 +0200 *************** *** 676,681 **** --- 676,684 ---- #ifdef FEAT_RUBY ruby_buffer_free(buf); #endif + #ifdef FEAT_JOB_CHANNEL + channel_buffer_free(buf); + #endif #ifdef FEAT_AUTOCMD aubuflocal_remove(buf); if (autocmd_busy) *** ../vim-7.4.1827/src/channel.c 2016-05-09 17:57:59.814722474 +0200 --- src/channel.c 2016-05-09 20:35:09.654594727 +0200 *************** *** 1068,1073 **** --- 1068,1074 ---- /* * Find a buffer matching "name" or create a new one. + * Returns NULL if there is something very wrong (error already reported). */ static buf_T * find_buffer(char_u *name, int err) *************** *** 1081,1086 **** --- 1082,1089 ---- { buf = buflist_new(name == NULL || *name == NUL ? NULL : name, NULL, (linenr_T)0, BLN_LISTED); + if (buf == NULL) + return NULL; buf_copy_options(buf, BCO_ENTER); curbuf = buf; #ifdef FEAT_QUICKFIX *************** *** 1187,1223 **** if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER) { /* writing output to a buffer. Default mode is NL. */ if (!(opt->jo_set & JO_OUT_MODE)) channel->ch_part[PART_OUT].ch_mode = MODE_NL; if (opt->jo_set & JO_OUT_BUF) ! channel->ch_part[PART_OUT].ch_buffer = ! buflist_findnr(opt->jo_io_buf[PART_OUT]); else ! channel->ch_part[PART_OUT].ch_buffer = ! find_buffer(opt->jo_io_name[PART_OUT], FALSE); ! ch_logs(channel, "writing out to buffer '%s'", ! (char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname); } if ((opt->jo_set & JO_ERR_IO) && (opt->jo_io[PART_ERR] == JIO_BUFFER || (opt->jo_io[PART_ERR] == JIO_OUT && (opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER))) { /* writing err to a buffer. Default mode is NL. */ if (!(opt->jo_set & JO_ERR_MODE)) channel->ch_part[PART_ERR].ch_mode = MODE_NL; if (opt->jo_io[PART_ERR] == JIO_OUT) ! channel->ch_part[PART_ERR].ch_buffer = ! channel->ch_part[PART_OUT].ch_buffer; else if (opt->jo_set & JO_ERR_BUF) ! channel->ch_part[PART_ERR].ch_buffer = ! buflist_findnr(opt->jo_io_buf[PART_ERR]); else ! channel->ch_part[PART_ERR].ch_buffer = ! find_buffer(opt->jo_io_name[PART_ERR], TRUE); ! ch_logs(channel, "writing err to buffer '%s'", ! (char *)channel->ch_part[PART_ERR].ch_buffer->b_ffname); } channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT]; --- 1190,1243 ---- if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER) { + buf_T *buf; + /* writing output to a buffer. Default mode is NL. */ if (!(opt->jo_set & JO_OUT_MODE)) channel->ch_part[PART_OUT].ch_mode = MODE_NL; if (opt->jo_set & JO_OUT_BUF) ! { ! buf = buflist_findnr(opt->jo_io_buf[PART_OUT]); ! if (buf == NULL) ! EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_OUT]); ! } else ! { ! buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE); ! } ! if (buf != NULL) ! { ! ch_logs(channel, "writing out to buffer '%s'", ! (char *)buf->b_ffname); ! channel->ch_part[PART_OUT].ch_buffer = buf; ! } } if ((opt->jo_set & JO_ERR_IO) && (opt->jo_io[PART_ERR] == JIO_BUFFER || (opt->jo_io[PART_ERR] == JIO_OUT && (opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER))) { + buf_T *buf; + /* writing err to a buffer. Default mode is NL. */ if (!(opt->jo_set & JO_ERR_MODE)) channel->ch_part[PART_ERR].ch_mode = MODE_NL; if (opt->jo_io[PART_ERR] == JIO_OUT) ! buf = channel->ch_part[PART_OUT].ch_buffer; else if (opt->jo_set & JO_ERR_BUF) ! { ! buf = buflist_findnr(opt->jo_io_buf[PART_ERR]); ! if (buf == NULL) ! EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]); ! } else ! buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE); ! if (buf != NULL) ! { ! ch_logs(channel, "writing err to buffer '%s'", ! (char *)buf->b_ffname); ! channel->ch_part[PART_ERR].ch_buffer = buf; ! } } channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT]; *************** *** 1388,1393 **** --- 1408,1432 ---- } /* + * Handle buffer "buf" beeing freed, remove it from any channels. + */ + void + channel_buffer_free(buf_T *buf) + { + channel_T *channel; + int part; + + for (channel = first_channel; channel != NULL; channel = channel->ch_next) + for (part = PART_SOCK; part <= PART_IN; ++part) + { + chanpart_T *ch_part = &channel->ch_part[part]; + + if (ch_part->ch_buffer == buf) + ch_part->ch_buffer = NULL; + } + } + + /* * Write any lines waiting to be written to a channel. */ void *** ../vim-7.4.1827/src/proto/channel.pro 2016-05-01 14:22:12.363965120 +0200 --- src/proto/channel.pro 2016-05-09 20:34:44.922875135 +0200 *************** *** 14,19 **** --- 14,20 ---- void channel_set_job(channel_T *channel, job_T *job, jobopt_T *options); void channel_set_options(channel_T *channel, jobopt_T *opt); void channel_set_req_callback(channel_T *channel, int part, char_u *callback, partial_T *partial, int id); + void channel_buffer_free(buf_T *buf); void channel_write_any_lines(void); void channel_write_new_lines(buf_T *buf); char_u *channel_get(channel_T *channel, int part); *** ../vim-7.4.1827/src/version.c 2016-05-09 17:57:59.814722474 +0200 --- src/version.c 2016-05-09 20:36:42.173545673 +0200 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 1828, /**/ -- SOLDIER: What? Ridden on a horse? ARTHUR: Yes! SOLDIER: You're using coconuts! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///