Subject: bug#48732: 28.0.50; lisp_string_width segfaults on startup under macOS

From: Naofumi Yasufuku <[email-masked]>
Date: Sun, 30 May 2021 18:06:33 +0900

Hi Eli,

> 2021/05/30 17:38、Eli Zaretskii <[email-masked]>のメール:
> 
> Maybe.  At least the user init file is processed during startup after
> the window-system was fully initialized.  The fontset you show in your
> crashed session also looks fine to me.  So I cannot explain why trying
> to find font for an Arabic character could crash for you.
> 
> Therefore, I went ahead and disabled accounting for automatic
> character compositions in 'format' and 'format-message'.  Only
> 'string-width' tries to account for that.  Please see if that solves
> your problem.
> 

No problem. I’ll try it.

>> This crash couldn’t be reproduced with full ${top_builddir}/src/.gdbinit settings,
>> so I copied ‘pp’ command definition to ${top_builddir}/.gdbinit then invoked
>> 'gdb ${top_builddir}/src/emacs' like this:
> 
> This in itself is very strange, and probably indicates that there's
> some memory-related problem somewhere.  If the change I installed
> solves your problem, I will try looking for such a problem.
> 

Yes, very strange. It seems memory or cache related.

I have tried to get simple printf logs of crashed `lface’  Lisp_Object access via
lisp_gtring_width()/find_automatic_composition() and free_realized_face().

According to the attached logs, find_automatic_composition() could attempt to access
to deallocated `lface’ objects on startup under macOS.

It could be macOS-specific because I have not seen such segfault under linux.

## Patch for realize_face, free_realized_face printf logs

attachment:
0001-free_realized_face-printf-logs-for-lisp_string_width.patch
init.el

Except for this printf patch, there is no difference of execution environment
described in previous email.

> 
> It seems that this segfault depends on some delicate matter of
> startup initialization timing.
> 
> This crash couldn’t be reproduced with full ${top_builddir}/src/.gdbinit settings,
> so I copied ‘pp’ command definition to ${top_builddir}/.gdbinit then invoked
> 'gdb ${top_builddir}/src/emacs' like this:
> 
> ```
> [naofumi@hyperion emacs (master)]% pwd
> /Users/naofumi/_git/git.sv.gnu.org/emacs
> [naofumi@hyperion emacs (master)]% 
> [naofumi@hyperion emacs (master)]% cat ./.gdbinit
> # Print out s-expressions
> define pp
>  set $tmp = $arg0
>  set $output_debug = print_output_debug_flag
>  set print_output_debug_flag = 0
>  call safe_debug_print ($tmp)
>  set print_output_debug_flag = $output_debug
> end
> document pp
> Print the argument as an emacs s-expression
> Works only when an inferior emacs is executing.
> end
> [naofumi@hyperion emacs (master)]% 
> [naofumi@hyperion emacs (master)]% 
> [naofumi@hyperion emacs (master)]% gdb ./src/emacs

## Case A) lisp_string_width segfault occurrs

attachment:
00_SEGFAULT-free_realized_face-gdb-grep-0x1032af4a0.txt
00_SEGFAULT-free_realized_face-gdb.txt.bz2
01_SEGFAULT-free_realized_face-gdb-grep-0x103435210.txt
01_SEGFAULT-free_realized_face-gdb.txt.bz2
--------------------------------------------------------------------------------------------------------------
realize_gui_face: make_realized_face: face=0x1032af4a0: face->lface=0x1032af4a0
realize_face: realize_gui_face: face=0x1032af4a0: face->lface=0x1032af4a0
free_realized_face: frame f=0x104197430: face=0x1032af4a0
xfree: block=0x1032af4a0
realize_gui_face: make_realized_face: face=0x1032af4a0: face->lface=0x1032af4a0
realize_face: realize_gui_face: face=0x1032af4a0: face->lface=0x1032af4a0
free_realized_face: frame f=0x104197430: face=0x1032af4a0
xfree: block=0x1032af4a0
realize_gui_face: make_realized_face: face=0x1032af4a0: face->lface=0x1032af4a0
realize_face: realize_gui_face: face=0x1032af4a0: face->lface=0x1032af4a0
font_range: frame f=0x104197430: face_id=0: face=0x1032af4a0
fontset_find_font: frame f=0x104197430: XFRAME(FONTSET_FRAME(fontset)=0x104197430: XFRAME(selected_frame)=0x104197430: face=0x1032af4a0
fontset_find_font: frame f=0x104197430: XFRAME(FONTSET_FRAME(fontset)=0x104197430: XFRAME(selected_frame)=0x104197430: face=0x1032af4a0
free_realized_face: frame f=0x104197430: face=0x1032af4a0
xfree: block=0x1032af4a0
font_select_entity: frame f=0x104197430: attrs=0x1032af4a0

Thread 2 received signal SIGSEGV, Segmentation fault.
0x0000000100291d05 in SYMBOL_NAME (sym=0x10421bc28) at ./lisp.h:2208
2208	  return XSYMBOL (sym)->u.s.name;
(gdb) bt
#0  0x0000000100291d05 in SYMBOL_NAME (sym=0x10421bc28) at ./lisp.h:2208
#1  0x00000001002917dd in font_style_to_value (prop=FONT_WEIGHT_INDEX, 
    val=0x10421bc28, noerror=true) at font.c:366
#2  0x000000010029a9c3 in font_select_entity (f=0x104197430, 
    entities=0x1038add13, attrs=0x1032af4a0, pixel_size=12, c=-1)
    at font.c:3158
#3  0x000000010029a569 in font_find_for_lface (f=0x104197430, 
    attrs=0x1032af4a0, spec=0x104909ded, c=-1) at font.c:3305
#4  0x000000010033c504 in fontset_find_font (fontset=0x104a05545, c=1603, 
    face=0x1032af4a0, charset_id=-1, fallback=false) at fontset.c:663
#5  0x00000001003350a4 in fontset_font (fontset=0x10421ae8d, c=1603, 
    face=0x1032af4a0, id=-1) at fontset.c:785
#6  0x000000010033569d in font_for_char (face=0x1032af4a0, c=1603, pos=308, 
    object=0x10317e5c4) at fontset.c:1066
#7  0x000000010029d15a in font_range (pos=309, pos_byte=336, 
    limit=0x7ffeefbf1310, w=0x104175c20, face=0x1032af4a0, string=0x10317e5c4)
    at font.c:3887
#8  0x00000001003283de in autocmp_chars (rule=0x105f2337d, charpos=308, 
    bytepos=334, limit=312, win=0x104175c20, face=0x0, string=0x10317e5c4, 
    direction=0x0) at composite.c:923
#9  0x000000010032932d in find_automatic_composition (pos=308, limit=308, 
    start=0x7ffeefbf15a8, end=0x7ffeefbf15a0, gstring=0x7ffeefbf15b8, 
    string=0x10317e5c4) at composite.c:1612
#10 0x0000000100127468 in lisp_string_width (string=0x10317e5c4, from=0, 
    to=479, precision=-1, nchars=0x7ffeefbf1a28, nbytes=0x7ffeefbf1a20)
    at character.c:375
#11 0x000000010025488b in styled_format (nargs=2, args=0x7ffeefbf74c0, 
    message=false) at editfns.c:3392
#12 0x000000010025283f in Fformat (nargs=2, args=0x7ffeefbf74c0)
    at editfns.c:3061
#13 0x000000010026e5eb in call3 (fn=0x100424ddd, arg1=0x1000000000, 
    arg2=0x7ffeefbf73f0, arg3=0x100271fb4 <xcdr_addr+20>) at eval.c:2912
#14 0x7830003700000806 in ?? ()
#15 0x0000000000000000 in ?? ()
(gdb) pp sym
[New Thread 0x1d0b of process 7056]
#<INVALID_LISP_OBJECT 0x10421bc28>
(gdb) up
#1  0x00000001002917dd in font_style_to_value (prop=FONT_WEIGHT_INDEX, 
    val=0x10421bc28, noerror=true) at font.c:366
366	      s = SSDATA (SYMBOL_NAME (val));
(gdb) up
#2  0x000000010029a9c3 in font_select_entity (f=0x104197430, 
    entities=0x1038add13, attrs=0x1032af4a0, pixel_size=12, c=-1)
    at font.c:3158
3158	    FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
(gdb) up
#3  0x000000010029a569 in font_find_for_lface (f=0x104197430, 
    attrs=0x1032af4a0, spec=0x104909ded, c=-1) at font.c:3305
3305			      val = font_select_entity (f, entities,
(gdb) up
#4  0x000000010033c504 in fontset_find_font (fontset=0x104a05545, c=1603, 
    face=0x1032af4a0, charset_id=-1, fallback=false) at fontset.c:663
663		  font_entity = font_find_for_lface (f, face->lface,
(gdb) pp face->lface[0]
nil
(gdb) pp face->lface[1]
#<INVALID_LISP_OBJECT 0x10421bc18>
(gdb) pp face->lface[2]
0
(gdb) pp face->lface[3]
#<INVALID_LISP_OBJECT 0xffffffffffffffff>
(gdb) pp face->lface[4]
nil
(gdb) pp face->lface[5]
#<INVALID_LISP_OBJECT 0x10421bc28>
(gdb) pp face->lface[6]
0
(gdb) pp face->lface[7]
#<INVALID_LISP_OBJECT 0xffffffffffffffff>
(gdb) pp face->lface
$1 = {0x0, 0x10421bc18, 0x2, 0xffffffffffffffff, 0x0, 0x10421bc28, 0x2, 
  0xffffffffffffffff, 0x0, 0x10421bc38, 0x2, 0xffffffffffffffff, 0x0, 
  0x10421bc48, 0x2, 0xffffffffffffffff, 0x0, 0x10421bc58, 0x2, 
  0xffffffffffffffff}
(gdb) q

--------------------------------------------------------------------------------------------------------------

##  Case B) No lisp_string_width segfault

attachment:
10_NO-SEGFAULT-free_realized_face-gdb-grep-0x1032cb260.txt
10_NO-SEGFAULT-free_realized_face-gdb.txt.bz2
11_NO-SEGFAULT-free_realized_face-gdb-grep-0x1031a5880.txt
11_NO-SEGFAULT-free_realized_face-gdb.txt.bz2
--------------------------------------------------------------------------------------------------------------
realize_gui_face: make_realized_face: face=0x1032cb260: face->lface=0x1032cb260
realize_face: realize_gui_face: face=0x1032cb260: face->lface=0x1032cb260
free_realized_face: frame f=0x108088e30: face=0x1032cb260
xfree: block=0x1032cb260
realize_gui_face: make_realized_face: face=0x1032cb260: face->lface=0x1032cb260
realize_face: realize_gui_face: face=0x1032cb260: face->lface=0x1032cb260
font_range: frame f=0x108088e30: face_id=0: face=0x1032cb260
fontset_find_font: frame f=0x108088e30: XFRAME(FONTSET_FRAME(fontset)=0x108088e30: XFRAME(selected_frame)=0x108088e30: face=0x1032cb260
fontset_find_font: frame f=0x108088e30: XFRAME(FONTSET_FRAME(fontset)=0x108088e30: XFRAME(selected_frame)=0x108088e30: face=0x1032cb260
free_realized_face: frame f=0x108088e30: face=0x1032cb260
xfree: block=0x1032cb260
realize_gui_face: make_realized_face: face=0x1032cb260: face->lface=0x1032cb260
realize_face: realize_gui_face: face=0x1032cb260: face->lface=0x1032cb260
font_select_entity: frame f=0x108088e30: attrs=0x1032cb260

--------------------------------------------------------------------------------------------------------------

Regards,
—Naofumi