Subject: bug#18659: 24.3.94; Crash in deselect_palette (Cygwin-w32 build)

From: Eli Zaretskii <[email-masked]>
Date: Wed, 08 Oct 2014 11:17:16 +0300

> Date: Tue, 07 Oct 2014 16:02:02 -0400
> From: Ken Brown <[email-masked]>
> 
> I just tried to view an emacs window that had been idle for a long time. 
>   I don't remember if I was using Alt-Tab to cycle through the open 
> windows or if I clicked on the emacs icon in the task bar.  When I 
> couldn't get to the window, I checked the terminal from which I had 
> started emacs under gdb, and I saw that emacs had crashed:
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x000000010068e6c9 in deselect_palette (f=0x0, hdc=0x0)
>      at /usr/src/debug/emacs-24.3.94-1/src/w32xfns.c:123
> 123       if (f->output_data.w32->old_palette)

It crashes because f is a NULL pointer, and the code tries to
dereference that.

> (gdb) bt
> #0  0x000000010068e6c9 in deselect_palette (f=0x0, hdc=0x0)
>      at /usr/src/debug/emacs-24.3.94-1/src/w32xfns.c:123
> #1  0x000000010068e798 in release_frame_dc (f=0x0, hdc=0x0)
>      at /usr/src/debug/emacs-24.3.94-1/src/w32xfns.c:154
> #2  0x0000000100691df6 in uniscribe_encode_char (font=0x1010f5e98 
> <bss_sbrk_buffer+6283800>, c=32) at 
> /usr/src/debug/emacs-24.3.94-1/src/w32uniscribe.c:585

I don't understand how could this lead to a crash.  Your detailed
backtrace shows:

> #2  0x0000000100691df6 in uniscribe_encode_char (font=0x1010f5e98 <bss_sbrk_buffer+6283800>, c=32) at /usr/src/debug/emacs-24.3.94-1/src/w32uniscribe.c:585
>         context = 0x0
>         f = 0x0
>         old_font = 0x0
>         code = 3
>         ch = L" \f"
>         len = 1
>         items = 0x427fa0
>         nitems = 1
>         uniscribe_font = 0x1010f5e98 <bss_sbrk_buffer+6283800>

Note that both 'context' and 'f' are NULL pointers.  But the source
around line 585 says this:

    if (context)
      {
	SelectObject (context, old_font);
	release_frame_dc (f, context);
      }

So why release_frame_dc is being called when 'context' is NULL??
Moreover, 'old_font' is also NULL, which means we never were in this
part of the code:

          if (result == E_PENDING)
            {
              /* Use selected frame until API is updated to pass
                 the frame.  */
              f = XFRAME (selected_frame);
              context = get_frame_dc (f);
              old_font = SelectObject (context, FONT_HANDLE (font));
              result = ScriptShape (context, &(uniscribe_font->cache),
                                    ch, len, 2, &(items[0].a),
                                    glyphs, clusters, attrs, &nglyphs);
            }

which is the only part that sets these 3 variables to something
non-NULL, and requires the call to release_frame_dc to avoid leaking
GDI objects, in this case the font we opened.

What's going on here? is this another case of "bidi_check_type
crashes"?