diff options
| author | Paul Eggert | 2019-01-31 10:29:50 -0800 |
|---|---|---|
| committer | Paul Eggert | 2019-01-31 10:31:43 -0800 |
| commit | 05d2fc7170fb66a87601b1c76ddae2c1b7b4b934 (patch) | |
| tree | 217ddd3a45ea611069d85ac13e22e525bb965996 /src/lisp.h | |
| parent | a68eee50eb515b28b448894299334afced26ef78 (diff) | |
| download | emacs-05d2fc7170fb66a87601b1c76ddae2c1b7b4b934.tar.gz emacs-05d2fc7170fb66a87601b1c76ddae2c1b7b4b934.zip | |
Widen modiff counts to avoid wraparound
Widen modification counts to at least 64 bits, to make
wraparound practically impossible.
* doc/lispref/buffers.texi (Buffer Modification):
Don’t say the modification-count can wrap around.
* src/buffer.c (Frestore_buffer_modified_p, Fbuffer_swap_text)
(modify_overlay):
* src/insdel.c (insert_1_both, insert_from_string_1)
(insert_from_gap, insert_from_buffer_1)
(adjust_after_replace, replace_range, replace_range_2)
(del_range_2, modify_text):
* src/textprop.c (modify_text_properties):
Use modiff_incr instead of incrementing directly.
(Fbuffer_modified_tick, Fbuffer_chars_modified_tick):
Don’t assume modification counts fit into fixnums.
* src/buffer.h (struct buffer_text, struct buffer):
* src/cmds.c (internal_self_insert):
* src/fileio.c (Finsert_file_contents):
* src/indent.c (last_known_column_modified):
* src/keyboard.c (command_loop_1):
* src/marker.c (cached_modiff):
* src/syntax.c (find_start_modiff, parse_sexp_propertize)
(find_defun_start):
* src/window.h (struct window):
Use modiff_count for modification counts.
* src/editfns.c (Fsubst_char_in_region):
Copy instead of incrementing modification counts,
since integer overflow checking is not needed here.
* src/lisp.h (modiff_count): New type.
(modiff_incr, modiff_to_integer): New inline functions.
* src/pdumper.c (dump_buffer): Update hash.
Diffstat (limited to 'src/lisp.h')
| -rw-r--r-- | src/lisp.h | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/src/lisp.h b/src/lisp.h index 5159f050a49..5a0de4b12c7 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3490,6 +3490,28 @@ integer_to_uintmax (Lisp_Object num, uintmax_t *n) | |||
| 3490 | } | 3490 | } |
| 3491 | } | 3491 | } |
| 3492 | 3492 | ||
| 3493 | /* A modification count. These are wide enough, and incremented | ||
| 3494 | rarely enough, so that they should never overflow a 60-bit counter | ||
| 3495 | in practice, and the code below assumes this so a compiler can | ||
| 3496 | generate better code if EMACS_INT is 64 bits. */ | ||
| 3497 | typedef intmax_t modiff_count; | ||
| 3498 | |||
| 3499 | INLINE modiff_count | ||
| 3500 | modiff_incr (modiff_count *a) | ||
| 3501 | { | ||
| 3502 | modiff_count a0 = *a; | ||
| 3503 | bool modiff_overflow = INT_ADD_WRAPV (a0, 1, a); | ||
| 3504 | eassert (!modiff_overflow && *a >> 30 >> 30 == 0); | ||
| 3505 | return a0; | ||
| 3506 | } | ||
| 3507 | |||
| 3508 | INLINE Lisp_Object | ||
| 3509 | modiff_to_integer (modiff_count a) | ||
| 3510 | { | ||
| 3511 | eassume (0 <= a && a >> 30 >> 30 == 0); | ||
| 3512 | return make_int (a); | ||
| 3513 | } | ||
| 3514 | |||
| 3493 | /* Defined in data.c. */ | 3515 | /* Defined in data.c. */ |
| 3494 | extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object); | 3516 | extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object); |
| 3495 | extern void notify_variable_watchers (Lisp_Object, Lisp_Object, | 3517 | extern void notify_variable_watchers (Lisp_Object, Lisp_Object, |