aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2013-01-18 10:32:12 +0400
committerDmitry Antipov2013-01-18 10:32:12 +0400
commite07469fa51b2955391255f54917ffb34efd66f1f (patch)
treec1d5d48ed06bb7c11b5ad1fc06229e92d1e50ada /src
parent6772211202c57f0dc96e5725f882a2fa4ee98d2d (diff)
downloademacs-e07469fa51b2955391255f54917ffb34efd66f1f.tar.gz
emacs-e07469fa51b2955391255f54917ffb34efd66f1f.zip
Fix crash when inserting data from non-regular files. See
http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00406.html for the error description produced by valgrind. * fileio.c (read_non_regular): Rename to read_contents. Free Lisp_Save_Value object used to pass parameters. (read_non_regular_quit): Rename to read_contents_quit. (Finsert_file_contents): Redesign internal file reading loop to adjust gap and end positions after each read and so help make_gap to work properly. Do not signal an I/O error too early and so do not leave not yet decoded characters in a buffer, which was the reason of redisplay crash. Use list2 to build return value. Adjust comments.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog14
-rw-r--r--src/fileio.c174
2 files changed, 86 insertions, 102 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index f53b9a70e97..a7b8ab7855b 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,17 @@
12013-01-18 Dmitry Antipov <dmantipov@yandex.ru>
2
3 Fix crash when inserting data from non-regular files. See
4 http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00406.html
5 for the error description produced by valgrind.
6 * fileio.c (read_non_regular): Rename to read_contents.
7 Free Lisp_Save_Value object used to pass parameters.
8 (read_non_regular_quit): Rename to read_contents_quit.
9 (Finsert_file_contents): Redesign internal file reading loop to adjust
10 gap and end positions after each read and so help make_gap to work
11 properly. Do not signal an I/O error too early and so do not leave
12 not yet decoded characters in a buffer, which was the reason of
13 redisplay crash. Use list2 to build return value. Adjust comments.
14
12013-01-17 Paul Eggert <eggert@cs.ucla.edu> 152013-01-17 Paul Eggert <eggert@cs.ucla.edu>
2 16
3 Close a race when statting and reading files (Bug#13149). 17 Close a race when statting and reading files (Bug#13149).
diff --git a/src/fileio.c b/src/fileio.c
index 41b8ae388d1..4c54fd822ae 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3408,13 +3408,13 @@ decide_coding_unwind (Lisp_Object unwind_data)
3408 return Qnil; 3408 return Qnil;
3409} 3409}
3410 3410
3411/* Read from a non-regular file. STATE is a Lisp_Save_Value 3411/* Check quit and read from the file. STATE is a Lisp_Save_Value
3412 object where slot 0 is the file descriptor, slot 1 specifies 3412 object where slot 0 is the file descriptor, slot 1 specifies
3413 an offset to put the read bytes, and slot 2 is the maximum 3413 an offset to put the read bytes, and slot 2 is the maximum
3414 amount of bytes to read. Value is the number of bytes read. */ 3414 amount of bytes to read. Value is the number of bytes read. */
3415 3415
3416static Lisp_Object 3416static Lisp_Object
3417read_non_regular (Lisp_Object state) 3417read_contents (Lisp_Object state)
3418{ 3418{
3419 int nbytes; 3419 int nbytes;
3420 3420
@@ -3425,15 +3425,15 @@ read_non_regular (Lisp_Object state)
3425 + XSAVE_INTEGER (state, 1)), 3425 + XSAVE_INTEGER (state, 1)),
3426 XSAVE_INTEGER (state, 2)); 3426 XSAVE_INTEGER (state, 2));
3427 immediate_quit = 0; 3427 immediate_quit = 0;
3428 /* Fast recycle this object for the likely next call. */
3429 free_misc (state);
3428 return make_number (nbytes); 3430 return make_number (nbytes);
3429} 3431}
3430 3432
3431 3433/* Condition-case handler used when reading files in insert-file-contents. */
3432/* Condition-case handler used when reading from non-regular files
3433 in insert-file-contents. */
3434 3434
3435static Lisp_Object 3435static Lisp_Object
3436read_non_regular_quit (Lisp_Object ignore) 3436read_contents_quit (Lisp_Object ignore)
3437{ 3437{
3438 return Qnil; 3438 return Qnil;
3439} 3439}
@@ -3505,7 +3505,7 @@ by calling `format-decode', which see. */)
3505 Lisp_Object p; 3505 Lisp_Object p;
3506 ptrdiff_t total = 0; 3506 ptrdiff_t total = 0;
3507 bool not_regular = 0; 3507 bool not_regular = 0;
3508 int save_errno = 0; 3508 int save_errno = 0, read_errno = 0;
3509 char read_buf[READ_BUF_SIZE]; 3509 char read_buf[READ_BUF_SIZE];
3510 struct coding_system coding; 3510 struct coding_system coding;
3511 char buffer[1 << 14]; 3511 char buffer[1 << 14];
@@ -4195,88 +4195,72 @@ by calling `format-decode', which see. */)
4195 Fcons (orig_filename, Qnil)); 4195 Fcons (orig_filename, Qnil));
4196 } 4196 }
4197 4197
4198 /* In the following loop, HOW_MUCH contains the total bytes read so 4198 /* In the following loop, HOW_MUCH contains the total bytes read
4199 far for a regular file, and not changed for a special file. But, 4199 so far for a regular file, and not changed for a special file. */
4200 before exiting the loop, it is set to a negative value if I/O
4201 error occurs. */
4202 how_much = 0; 4200 how_much = 0;
4203 4201
4204 /* Total bytes inserted. */ 4202 /* Total bytes inserted. */
4205 inserted = 0; 4203 inserted = 0;
4206 4204
4207 /* Here, we don't do code conversion in the loop. It is done by 4205 /* Here we don't do code conversion in the loop. It is done by
4208 decode_coding_gap after all data are read into the buffer. */ 4206 decode_coding_gap after all data are read into the buffer, or
4209 { 4207 reading loop is interrupted with quit or due to I/O error. */
4210 ptrdiff_t gap_size = GAP_SIZE;
4211
4212 while (how_much < total)
4213 {
4214 /* try is reserved in some compilers (Microsoft C) */
4215 ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE);
4216 ptrdiff_t this;
4217
4218 if (not_regular)
4219 {
4220 Lisp_Object nbytes;
4221
4222 /* Maybe make more room. */
4223 if (gap_size < trytry)
4224 {
4225 make_gap (total - gap_size);
4226 gap_size = GAP_SIZE;
4227 }
4228
4229 /* Read from the file, capturing `quit'. When an
4230 error occurs, end the loop, and arrange for a quit
4231 to be signaled after decoding the text we read. */
4232 nbytes = internal_condition_case_1
4233 (read_non_regular,
4234 make_save_value ("iii", (ptrdiff_t) fd, inserted, trytry),
4235 Qerror, read_non_regular_quit);
4236
4237 if (NILP (nbytes))
4238 {
4239 read_quit = 1;
4240 break;
4241 }
4242
4243 this = XINT (nbytes);
4244 }
4245 else
4246 {
4247 /* Allow quitting out of the actual I/O. We don't make text
4248 part of the buffer until all the reading is done, so a C-g
4249 here doesn't do any harm. */
4250 immediate_quit = 1;
4251 QUIT;
4252 this = emacs_read (fd,
4253 ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
4254 + inserted),
4255 trytry);
4256 immediate_quit = 0;
4257 }
4258
4259 if (this <= 0)
4260 {
4261 how_much = this;
4262 break;
4263 }
4264 4208
4265 gap_size -= this; 4209 while (how_much < total)
4210 {
4211 ptrdiff_t nread, maxread = min (total - how_much, READ_BUF_SIZE);
4212 Lisp_Object result;
4213
4214 /* For a special file, gap is enlarged as we read,
4215 so GAP_SIZE should be checked every time. */
4216 if (not_regular && (GAP_SIZE < maxread))
4217 make_gap (maxread - GAP_SIZE);
4218
4219 /* Read from the file, capturing `quit'. */
4220 result = internal_condition_case_1
4221 (read_contents,
4222 make_save_value ("iii", (ptrdiff_t) fd, inserted, maxread),
4223 Qerror, read_contents_quit);
4224 if (NILP (result))
4225 {
4226 /* Quit is signaled. End the loop and arrange
4227 real quit after decoding the text we read. */
4228 read_quit = 1;
4229 break;
4230 }
4231 nread = XINT (result);
4232 if (nread <= 0)
4233 {
4234 /* End of file or I/O error. End the loop and
4235 save error code in case of I/O error. */
4236 if (nread < 0)
4237 read_errno = errno;
4238 break;
4239 }
4266 4240
4267 /* For a regular file, where TOTAL is the real size, 4241 /* Adjust gap and end positions. */
4268 count HOW_MUCH to compare with it. 4242 GAP_SIZE -= nread;
4269 For a special file, where TOTAL is just a buffer size, 4243 GPT += nread;
4270 so don't bother counting in HOW_MUCH. 4244 ZV += nread;
4271 (INSERTED is where we count the number of characters inserted.) */ 4245 Z += nread;
4272 if (! not_regular) 4246 GPT_BYTE += nread;
4273 how_much += this; 4247 ZV_BYTE += nread;
4274 inserted += this; 4248 Z_BYTE += nread;
4275 } 4249 if (GAP_SIZE > 0)
4276 } 4250 *(GPT_ADDR) = 0;
4251
4252 /* For a regular file, where TOTAL is the real size, count HOW_MUCH to
4253 compare with it. For a special file, where TOTAL is just a buffer
4254 size, don't bother counting in HOW_MUCH, but always accumulate the
4255 number of bytes read in INSERTED. */
4256 if (!not_regular)
4257 how_much += nread;
4258 inserted += nread;
4259 }
4277 4260
4278 /* Now we have read all the file data into the gap. 4261 /* Now we have either read all the file data into the gap,
4279 If it was empty, undo marking the buffer modified. */ 4262 or stop reading on I/O error or quit. If nothing was
4263 read, undo marking the buffer modified. */
4280 4264
4281 if (inserted == 0) 4265 if (inserted == 0)
4282 { 4266 {
@@ -4289,28 +4273,11 @@ by calling `format-decode', which see. */)
4289 else 4273 else
4290 Vdeactivate_mark = Qt; 4274 Vdeactivate_mark = Qt;
4291 4275
4292 /* Make the text read part of the buffer. */
4293 GAP_SIZE -= inserted;
4294 GPT += inserted;
4295 GPT_BYTE += inserted;
4296 ZV += inserted;
4297 ZV_BYTE += inserted;
4298 Z += inserted;
4299 Z_BYTE += inserted;
4300
4301 if (GAP_SIZE > 0)
4302 /* Put an anchor to ensure multi-byte form ends at gap. */
4303 *GPT_ADDR = 0;
4304
4305 emacs_close (fd); 4276 emacs_close (fd);
4306 4277
4307 /* Discard the unwind protect for closing the file. */ 4278 /* Discard the unwind protect for closing the file. */
4308 specpdl_ptr--; 4279 specpdl_ptr--;
4309 4280
4310 if (how_much < 0)
4311 error ("IO error reading %s: %s",
4312 SDATA (orig_filename), emacs_strerror (errno));
4313
4314 notfound: 4281 notfound:
4315 4282
4316 if (NILP (coding_system)) 4283 if (NILP (coding_system))
@@ -4599,14 +4566,17 @@ by calling `format-decode', which see. */)
4599 report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); 4566 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
4600 } 4567 }
4601 4568
4569 /* There was an error reading file. */
4570 if (read_errno)
4571 error ("IO error reading %s: %s",
4572 SDATA (orig_filename), emacs_strerror (read_errno));
4573
4574 /* Quit was signaled. */
4602 if (read_quit) 4575 if (read_quit)
4603 Fsignal (Qquit, Qnil); 4576 Fsignal (Qquit, Qnil);
4604 4577
4605 /* ??? Retval needs to be dealt with in all cases consistently. */
4606 if (NILP (val)) 4578 if (NILP (val))
4607 val = Fcons (orig_filename, 4579 val = list2 (orig_filename, make_number (inserted));
4608 Fcons (make_number (inserted),
4609 Qnil));
4610 4580
4611 RETURN_UNGCPRO (unbind_to (count, val)); 4581 RETURN_UNGCPRO (unbind_to (count, val));
4612} 4582}