diff options
| author | Paul Eggert | 2019-10-30 14:17:40 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-10-30 14:43:14 -0700 |
| commit | 40ae02ff50a8f05660a7f9f234320875b6358c9d (patch) | |
| tree | c5d4a135409445f1886cda3001bfa41472f8b3fb /src | |
| parent | 94b8153eaa78e376e6ed8c2b04602edf3dadc007 (diff) | |
| download | emacs-40ae02ff50a8f05660a7f9f234320875b6358c9d.tar.gz emacs-40ae02ff50a8f05660a7f9f234320875b6358c9d.zip | |
Fix fileio.c infloops on circular lists
Fix infinite loops in fileio.c when a circular list is the
value of after_insert_file_functions,
buffer-auto-save-file-format, buffer-file-format, or
write-region-annotate-functions.
* src/fileio.c (Finsert_file_contents, build_annotations):
Use FOR_EACH_TAIL to avoid infloop on circular lists.
(build_annotations): Use an EMACS_INT, not an int, to count
nesting level.
* test/src/fileio-tests.el:
(fileio-tests--circular-after-insert-file-functions): New test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/src/fileio.c b/src/fileio.c index f1860e8a930..a3121a26dad 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -4742,7 +4742,7 @@ by calling `format-decode', which see. */) | |||
| 4742 | /* For consistency with format-decode call these now iff inserted > 0 | 4742 | /* For consistency with format-decode call these now iff inserted > 0 |
| 4743 | (martin 2007-06-28). */ | 4743 | (martin 2007-06-28). */ |
| 4744 | p = Vafter_insert_file_functions; | 4744 | p = Vafter_insert_file_functions; |
| 4745 | while (CONSP (p)) | 4745 | FOR_EACH_TAIL (p) |
| 4746 | { | 4746 | { |
| 4747 | if (NILP (replace)) | 4747 | if (NILP (replace)) |
| 4748 | { | 4748 | { |
| @@ -4782,9 +4782,6 @@ by calling `format-decode', which see. */) | |||
| 4782 | inserted = XFIXNAT (insval); | 4782 | inserted = XFIXNAT (insval); |
| 4783 | } | 4783 | } |
| 4784 | } | 4784 | } |
| 4785 | |||
| 4786 | maybe_quit (); | ||
| 4787 | p = XCDR (p); | ||
| 4788 | } | 4785 | } |
| 4789 | 4786 | ||
| 4790 | if (!empty_undo_list_p) | 4787 | if (!empty_undo_list_p) |
| @@ -5375,14 +5372,14 @@ build_annotations (Lisp_Object start, Lisp_Object end) | |||
| 5375 | Lisp_Object annotations; | 5372 | Lisp_Object annotations; |
| 5376 | Lisp_Object p, res; | 5373 | Lisp_Object p, res; |
| 5377 | Lisp_Object original_buffer; | 5374 | Lisp_Object original_buffer; |
| 5378 | int i; | ||
| 5379 | bool used_global = false; | 5375 | bool used_global = false; |
| 5380 | 5376 | ||
| 5381 | XSETBUFFER (original_buffer, current_buffer); | 5377 | XSETBUFFER (original_buffer, current_buffer); |
| 5382 | 5378 | ||
| 5383 | annotations = Qnil; | 5379 | annotations = Qnil; |
| 5384 | p = Vwrite_region_annotate_functions; | 5380 | p = Vwrite_region_annotate_functions; |
| 5385 | while (CONSP (p)) | 5381 | loop_over_p: |
| 5382 | FOR_EACH_TAIL (p) | ||
| 5386 | { | 5383 | { |
| 5387 | struct buffer *given_buffer = current_buffer; | 5384 | struct buffer *given_buffer = current_buffer; |
| 5388 | if (EQ (Qt, XCAR (p)) && !used_global) | 5385 | if (EQ (Qt, XCAR (p)) && !used_global) |
| @@ -5391,7 +5388,7 @@ build_annotations (Lisp_Object start, Lisp_Object end) | |||
| 5391 | p = CALLN (Fappend, | 5388 | p = CALLN (Fappend, |
| 5392 | Fdefault_value (Qwrite_region_annotate_functions), | 5389 | Fdefault_value (Qwrite_region_annotate_functions), |
| 5393 | XCDR (p)); | 5390 | XCDR (p)); |
| 5394 | continue; | 5391 | goto loop_over_p; |
| 5395 | } | 5392 | } |
| 5396 | Vwrite_region_annotations_so_far = annotations; | 5393 | Vwrite_region_annotations_so_far = annotations; |
| 5397 | res = call2 (XCAR (p), start, end); | 5394 | res = call2 (XCAR (p), start, end); |
| @@ -5411,7 +5408,6 @@ build_annotations (Lisp_Object start, Lisp_Object end) | |||
| 5411 | } | 5408 | } |
| 5412 | Flength (res); /* Check basic validity of return value */ | 5409 | Flength (res); /* Check basic validity of return value */ |
| 5413 | annotations = merge (annotations, res, Qcar_less_than_car); | 5410 | annotations = merge (annotations, res, Qcar_less_than_car); |
| 5414 | p = XCDR (p); | ||
| 5415 | } | 5411 | } |
| 5416 | 5412 | ||
| 5417 | /* Now do the same for annotation functions implied by the file-format */ | 5413 | /* Now do the same for annotation functions implied by the file-format */ |
| @@ -5419,7 +5415,8 @@ build_annotations (Lisp_Object start, Lisp_Object end) | |||
| 5419 | p = BVAR (current_buffer, auto_save_file_format); | 5415 | p = BVAR (current_buffer, auto_save_file_format); |
| 5420 | else | 5416 | else |
| 5421 | p = BVAR (current_buffer, file_format); | 5417 | p = BVAR (current_buffer, file_format); |
| 5422 | for (i = 0; CONSP (p); p = XCDR (p), ++i) | 5418 | EMACS_INT i = 0; |
| 5419 | FOR_EACH_TAIL (p) | ||
| 5423 | { | 5420 | { |
| 5424 | struct buffer *given_buffer = current_buffer; | 5421 | struct buffer *given_buffer = current_buffer; |
| 5425 | 5422 | ||
| @@ -5429,7 +5426,7 @@ build_annotations (Lisp_Object start, Lisp_Object end) | |||
| 5429 | has written annotations to a temporary buffer, which is now | 5426 | has written annotations to a temporary buffer, which is now |
| 5430 | current. */ | 5427 | current. */ |
| 5431 | res = call5 (Qformat_annotate_function, XCAR (p), start, end, | 5428 | res = call5 (Qformat_annotate_function, XCAR (p), start, end, |
| 5432 | original_buffer, make_fixnum (i)); | 5429 | original_buffer, make_fixnum (i++)); |
| 5433 | if (current_buffer != given_buffer) | 5430 | if (current_buffer != given_buffer) |
| 5434 | { | 5431 | { |
| 5435 | XSETFASTINT (start, BEGV); | 5432 | XSETFASTINT (start, BEGV); |