[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#36431: Crash in marker.c:337
From: |
Stefan Monnier |
Subject: |
bug#36431: Crash in marker.c:337 |
Date: |
Wed, 03 Jul 2019 00:21:54 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) |
> AFAICT, this patch moves the call to move_gap_both from a fragment
> where we must decode the inserted text to a fragment where such a
> decoding might not be necessary. If I'm right, then this makes
> insert-file-contents slower in some cases, because moving the gap
> might be very expensive with large buffers.
Here's an alternative patch which doesn't suffer from this problem but
also eliminates the transiently-inconsistent multibyte buffer situation.
Stefan
diff --git a/src/fileio.c b/src/fileio.c
index 2825c1b54c..9ed1fcf8ca 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3705,6 +3705,7 @@ because (1) it preserves some marker positions and (2) it
puts less data
CHECK_CODING_SYSTEM (Vcoding_system_for_read);
Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
}
+ eassert (inserted == 0);
goto notfound;
}
@@ -3731,7 +3732,10 @@ because (1) it preserves some marker positions and (2)
it puts less data
not_regular = 1;
if (! NILP (visit))
- goto notfound;
+ {
+ eassert (inserted == 0);
+ goto notfound;
+ }
if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
xsignal2 (Qfile_error,
@@ -4399,10 +4403,10 @@ because (1) it preserves some marker positions and (2)
it puts less data
if (how_much < 0)
report_file_error ("Read error", orig_filename);
- /* Make the text read part of the buffer. */
- insert_from_gap_1 (inserted, inserted, false);
-
- notfound:
+ notfound: ;
+ Lisp_Object multibyte
+ = BVAR (current_buffer, enable_multibyte_characters);
+ bool ingap = true; /* Bytes are currently in the gap. */
if (NILP (coding_system))
{
@@ -4411,6 +4415,7 @@ because (1) it preserves some marker positions and (2) it
puts less data
Note that we can get here only if the buffer was empty
before the insertion. */
+ eassert (Z == BEG);
if (!NILP (Vcoding_system_for_read))
coding_system = Vcoding_system_for_read;
@@ -4421,8 +4426,6 @@ because (1) it preserves some marker positions and (2) it
puts less data
enable-multibyte-characters directly here without taking
care of marker adjustment. By this way, we can run Lisp
program safely before decoding the inserted text. */
- Lisp_Object multibyte
- = BVAR (current_buffer, enable_multibyte_characters);
Lisp_Object undo_list = BVAR (current_buffer, undo_list);
ptrdiff_t count1 = SPECPDL_INDEX ();
@@ -4430,6 +4433,10 @@ because (1) it preserves some marker positions and (2)
it puts less data
bset_undo_list (current_buffer, Qt);
record_unwind_protect (restore_buffer, Fcurrent_buffer ());
+ /* Make the text read part of the buffer. */
+ insert_from_gap_1 (inserted, inserted, false);
+ ingap = false;
+
if (inserted > 0 && ! NILP (Vset_auto_coding_function))
{
coding_system = call2 (Vset_auto_coding_function,
@@ -4455,15 +4462,10 @@ because (1) it preserves some marker positions and (2)
it puts less data
adjust_overlays_for_delete (BEG, Z - BEG);
set_buffer_intervals (current_buffer, NULL);
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
-
- /* Change the buffer's multibyteness directly. We used to do this
- from within unbind_to, but it was unsafe since the bytes
- may contain invalid sequences for a multibyte buffer (which is OK
- here since we'll decode them before anyone else gets to see
- them, but is dangerous when we're doing a non-local exit). */
- bset_enable_multibyte_characters (current_buffer, multibyte);
bset_undo_list (current_buffer, undo_list);
inserted = Z_BYTE - BEG_BYTE;
+ /* The bytes may be invalid for a multibyte buffer, so we can't
+ restore the multibyteness yet. */
}
if (NILP (coding_system))
@@ -4471,7 +4473,7 @@ because (1) it preserves some marker positions and (2) it
puts less data
else
CHECK_CODING_SYSTEM (coding_system);
- if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ if (NILP (multibyte))
/* We must suppress all character code conversion except for
end-of-line conversion. */
coding_system = raw_text_coding_system (coding_system);
@@ -4490,33 +4492,51 @@ because (1) it preserves some marker positions and (2)
it puts less data
{
/* Visiting a file with these coding system makes the buffer
unibyte. */
- if (inserted > 0)
+ if (!ingap)
+ multibyte = Qnil;
+ else if (inserted > 0)
bset_enable_multibyte_characters (current_buffer, Qnil);
- else
+ else
Fset_buffer_multibyte (Qnil);
}
}
- coding.dst_multibyte = ! NILP (BVAR (current_buffer,
enable_multibyte_characters));
+ coding.dst_multibyte = !NILP (multibyte);
if (CODING_MAY_REQUIRE_DECODING (&coding)
&& (inserted > 0 || CODING_REQUIRE_FLUSHING (&coding)))
{
- move_gap_both (PT, PT_BYTE);
- GAP_SIZE += inserted;
- ZV_BYTE -= inserted;
- Z_BYTE -= inserted;
- ZV -= inserted;
- Z -= inserted;
+ if (ingap)
+ { /* Text is at beginning of gap, move it to the end. */
+ memmove (GAP_END_ADDR - inserted, GPT_ADDR, inserted);
+ }
+ else
+ { /* Text is inside the buffer; move it to end of the gap. */
+ move_gap_both (PT, PT_BYTE);
+ eassert (inserted == Z_BYTE - BEG_BYTE);
+ GAP_SIZE += inserted;
+ ZV = Z = GPT = BEG;
+ ZV_BYTE = Z_BYTE = GPT_BYTE = BEG_BYTE;
+ /* Now we are safe to change the buffer's multibyteness directly. */
+ bset_enable_multibyte_characters (current_buffer, multibyte);
+ }
+
decode_coding_gap (&coding, inserted);
inserted = coding.produced_char;
coding_system = CODING_ID_NAME (coding.id);
}
- else if (inserted > 0)
+ else if (inserted > 0 && ingap)
{
+ /* Make the text read part of the buffer. */
+ eassert (NILP (BVAR (current_buffer, enable_multibyte_characters)));
+ insert_from_gap_1 (inserted, inserted, false);
invalidate_buffer_caches (current_buffer, PT, PT + inserted);
adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted,
inserted);
}
+ else if (!ingap)
+ { /* Apparently, no decoding needed, so just set the bytenesss. */
+ bset_enable_multibyte_characters (current_buffer, multibyte);
+ }
/* Call after-change hooks for the inserted text, aside from the case
of normal visiting (not with REPLACE), which is done in a new buffer
- bug#36431: Crash in marker.c:337, (continued)
- bug#36431: Crash in marker.c:337, Eli Zaretskii, 2019/07/02
- bug#36431: Crash in marker.c:337, Stefan Monnier, 2019/07/02
- bug#36431: Crash in marker.c:337, Eli Zaretskii, 2019/07/02
- bug#36431: Crash in marker.c:337, Stefan Monnier, 2019/07/02
- bug#36431: Crash in marker.c:337, Eli Zaretskii, 2019/07/02
- bug#36431: Crash in marker.c:337, Stefan Monnier, 2019/07/02
- bug#36431: Crash in marker.c:337, Eli Zaretskii, 2019/07/03
- bug#36431: Crash in marker.c:337, Stefan Monnier, 2019/07/03
- bug#36431: Crash in marker.c:337, Eli Zaretskii, 2019/07/03
bug#36431: Crash in marker.c:337,
Stefan Monnier <=
bug#36431: Crash in marker.c:337, Stefan Monnier, 2019/07/03
bug#36431: Crash in marker.c:337, Stefan Monnier, 2019/07/09