Mercurial > vim
comparison src/channel.c @ 9087:d4606ae170aa v7.4.1828
commit https://github.com/vim/vim/commit/e0f76d00979c972329f6c371463a20da61ccad65
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon May 9 20:38:53 2016 +0200
patch 7.4.1828
Problem: May try to access buffer that's already freed.
Solution: When freeing a buffer remove it from any channel.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 09 May 2016 20:45:08 +0200 |
parents | d362e6df1deb |
children | 6bc0a492e8ba |
comparison
equal
deleted
inserted
replaced
9086:75f46a491f61 | 9087:d4606ae170aa |
---|---|
1066 } | 1066 } |
1067 } | 1067 } |
1068 | 1068 |
1069 /* | 1069 /* |
1070 * Find a buffer matching "name" or create a new one. | 1070 * Find a buffer matching "name" or create a new one. |
1071 * Returns NULL if there is something very wrong (error already reported). | |
1071 */ | 1072 */ |
1072 static buf_T * | 1073 static buf_T * |
1073 find_buffer(char_u *name, int err) | 1074 find_buffer(char_u *name, int err) |
1074 { | 1075 { |
1075 buf_T *buf = NULL; | 1076 buf_T *buf = NULL; |
1079 buf = buflist_findname(name); | 1080 buf = buflist_findname(name); |
1080 if (buf == NULL) | 1081 if (buf == NULL) |
1081 { | 1082 { |
1082 buf = buflist_new(name == NULL || *name == NUL ? NULL : name, | 1083 buf = buflist_new(name == NULL || *name == NUL ? NULL : name, |
1083 NULL, (linenr_T)0, BLN_LISTED); | 1084 NULL, (linenr_T)0, BLN_LISTED); |
1085 if (buf == NULL) | |
1086 return NULL; | |
1084 buf_copy_options(buf, BCO_ENTER); | 1087 buf_copy_options(buf, BCO_ENTER); |
1085 curbuf = buf; | 1088 curbuf = buf; |
1086 #ifdef FEAT_QUICKFIX | 1089 #ifdef FEAT_QUICKFIX |
1087 set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); | 1090 set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); |
1088 set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL); | 1091 set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL); |
1185 ++(*pp)->pt_refcount; | 1188 ++(*pp)->pt_refcount; |
1186 } | 1189 } |
1187 | 1190 |
1188 if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER) | 1191 if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER) |
1189 { | 1192 { |
1193 buf_T *buf; | |
1194 | |
1190 /* writing output to a buffer. Default mode is NL. */ | 1195 /* writing output to a buffer. Default mode is NL. */ |
1191 if (!(opt->jo_set & JO_OUT_MODE)) | 1196 if (!(opt->jo_set & JO_OUT_MODE)) |
1192 channel->ch_part[PART_OUT].ch_mode = MODE_NL; | 1197 channel->ch_part[PART_OUT].ch_mode = MODE_NL; |
1193 if (opt->jo_set & JO_OUT_BUF) | 1198 if (opt->jo_set & JO_OUT_BUF) |
1194 channel->ch_part[PART_OUT].ch_buffer = | 1199 { |
1195 buflist_findnr(opt->jo_io_buf[PART_OUT]); | 1200 buf = buflist_findnr(opt->jo_io_buf[PART_OUT]); |
1201 if (buf == NULL) | |
1202 EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_OUT]); | |
1203 } | |
1196 else | 1204 else |
1197 channel->ch_part[PART_OUT].ch_buffer = | 1205 { |
1198 find_buffer(opt->jo_io_name[PART_OUT], FALSE); | 1206 buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE); |
1199 ch_logs(channel, "writing out to buffer '%s'", | 1207 } |
1200 (char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname); | 1208 if (buf != NULL) |
1209 { | |
1210 ch_logs(channel, "writing out to buffer '%s'", | |
1211 (char *)buf->b_ffname); | |
1212 channel->ch_part[PART_OUT].ch_buffer = buf; | |
1213 } | |
1201 } | 1214 } |
1202 | 1215 |
1203 if ((opt->jo_set & JO_ERR_IO) && (opt->jo_io[PART_ERR] == JIO_BUFFER | 1216 if ((opt->jo_set & JO_ERR_IO) && (opt->jo_io[PART_ERR] == JIO_BUFFER |
1204 || (opt->jo_io[PART_ERR] == JIO_OUT && (opt->jo_set & JO_OUT_IO) | 1217 || (opt->jo_io[PART_ERR] == JIO_OUT && (opt->jo_set & JO_OUT_IO) |
1205 && opt->jo_io[PART_OUT] == JIO_BUFFER))) | 1218 && opt->jo_io[PART_OUT] == JIO_BUFFER))) |
1206 { | 1219 { |
1220 buf_T *buf; | |
1221 | |
1207 /* writing err to a buffer. Default mode is NL. */ | 1222 /* writing err to a buffer. Default mode is NL. */ |
1208 if (!(opt->jo_set & JO_ERR_MODE)) | 1223 if (!(opt->jo_set & JO_ERR_MODE)) |
1209 channel->ch_part[PART_ERR].ch_mode = MODE_NL; | 1224 channel->ch_part[PART_ERR].ch_mode = MODE_NL; |
1210 if (opt->jo_io[PART_ERR] == JIO_OUT) | 1225 if (opt->jo_io[PART_ERR] == JIO_OUT) |
1211 channel->ch_part[PART_ERR].ch_buffer = | 1226 buf = channel->ch_part[PART_OUT].ch_buffer; |
1212 channel->ch_part[PART_OUT].ch_buffer; | |
1213 else if (opt->jo_set & JO_ERR_BUF) | 1227 else if (opt->jo_set & JO_ERR_BUF) |
1214 channel->ch_part[PART_ERR].ch_buffer = | 1228 { |
1215 buflist_findnr(opt->jo_io_buf[PART_ERR]); | 1229 buf = buflist_findnr(opt->jo_io_buf[PART_ERR]); |
1230 if (buf == NULL) | |
1231 EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]); | |
1232 } | |
1216 else | 1233 else |
1217 channel->ch_part[PART_ERR].ch_buffer = | 1234 buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE); |
1218 find_buffer(opt->jo_io_name[PART_ERR], TRUE); | 1235 if (buf != NULL) |
1219 ch_logs(channel, "writing err to buffer '%s'", | 1236 { |
1220 (char *)channel->ch_part[PART_ERR].ch_buffer->b_ffname); | 1237 ch_logs(channel, "writing err to buffer '%s'", |
1238 (char *)buf->b_ffname); | |
1239 channel->ch_part[PART_ERR].ch_buffer = buf; | |
1240 } | |
1221 } | 1241 } |
1222 | 1242 |
1223 channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT]; | 1243 channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT]; |
1224 channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR]; | 1244 channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR]; |
1225 channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN]; | 1245 channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN]; |
1383 ch_log(channel, "Finished writing all lines to channel"); | 1403 ch_log(channel, "Finished writing all lines to channel"); |
1384 } | 1404 } |
1385 else | 1405 else |
1386 ch_logn(channel, "Still %d more lines to write", | 1406 ch_logn(channel, "Still %d more lines to write", |
1387 buf->b_ml.ml_line_count - lnum + 1); | 1407 buf->b_ml.ml_line_count - lnum + 1); |
1408 } | |
1409 | |
1410 /* | |
1411 * Handle buffer "buf" beeing freed, remove it from any channels. | |
1412 */ | |
1413 void | |
1414 channel_buffer_free(buf_T *buf) | |
1415 { | |
1416 channel_T *channel; | |
1417 int part; | |
1418 | |
1419 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | |
1420 for (part = PART_SOCK; part <= PART_IN; ++part) | |
1421 { | |
1422 chanpart_T *ch_part = &channel->ch_part[part]; | |
1423 | |
1424 if (ch_part->ch_buffer == buf) | |
1425 ch_part->ch_buffer = NULL; | |
1426 } | |
1388 } | 1427 } |
1389 | 1428 |
1390 /* | 1429 /* |
1391 * Write any lines waiting to be written to a channel. | 1430 * Write any lines waiting to be written to a channel. |
1392 */ | 1431 */ |