[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#65060: 29.1.50; display_count_lines segv
From: |
Eli Zaretskii |
Subject: |
bug#65060: 29.1.50; display_count_lines segv |
Date: |
Sat, 05 Aug 2023 09:24:01 +0300 |
> From: Kai Ma <justksqsf@gmail.com>
> Date: Sat, 05 Aug 2023 05:41:54 +0800
>
>
> Emacs can crash due to memchr on null pointers inside
> display_count_lines:
>
> * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
> (code=1, address=0x0)
> frame #0: 0x00007ff813c6329d
> libsystem_platform.dylib`_platform_memchr$VARIANT$Haswell + 29
> * frame #1: 0x000000010005c1ef emacs`display_count_lines(start_byte=1,
> limit_byte=650, count=17166, byte_pos_ptr=0x00007ff7bfef2ef8) at
> xdisp.c:28475:14
This crash is inside redisplay, which displays the mode line. That
calls some Lisp (probably because some mode-line element uses :eval),
which calls format-mode-line (a _really_ bad idea), which again calls
Lisp (due to :eval?), which calls line-number-at-pos, which crashes.
> I took a quick look at the function, and it turns out the cursor can be
> null even on the first iteration. After applying the following change,
> I can see "cursor is null" printed out just before the crash.
>
> diff --git a/src/xdisp.c b/src/xdisp.c
> index 9cddcfeda27..f994021bb3c 100644
> --- a/src/xdisp.c
> +++ b/src/xdisp.c
> @@ -28457,6 +28457,8 @@ display_count_lines (ptrdiff_t start_byte,
> ceiling = min (limit_byte - 1, ceiling);
> ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
> base = (cursor = BYTE_POS_ADDR (start_byte));
> + if (! cursor)
> + fprintf (stderr, "cursor is null\n");
That's most probably a sign of some other bug elsewhere.
BYTE_POS_ADDR returns the pointer to buffer text, so it cannot be a
NULL pointer, unless something really catastrophic happened, like the
current buffer was killed behind redisplay's back.
Please add to the fprintf the following data:
GPT_BYTE
GAP_SIZE
BEG_ADDR
current_buffer->text->beg
and show the result.
My guess is that current_buffer->text->beg is NULL, which means the
current buffer was killed, and then the bug is where this happens, not
in display_count_lines. Most probably, dirvish does something that
kills the buffer that is the current one when format-mode-line is
called.
> 1. Create init.el
>
> (require 'package)
> (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")
> t)
> (use-package dirvish :ensure t :config (dirvish-override-dired-mode))
> (global-display-line-numbers-mode +1)
> (dirvish-override-dired-mode)
>
> 2. emacs -q -l init.el
>
> 3. M-x dirvish
>
> 4. randomly kill dirvish buffers, and/or randomly delete dirvish windows.
>
> Chances are, at some point, Emacs crashes due to the above segv. I have
> reproduced the crash in emacs -q, but it was not easy. I will try to
> find a better recipe and post it here.
I tried to use this, but couldn't cause Emacs crash. And I don't
think the reproduction is really necessary, if we establish that the
current buffer is dead when format-mode-line is called in this case.