From 29ff903bb0379f6fef0f7dc60977e05a8c60f147 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 3 Mar 2022 20:31:33 +0200 Subject: [PATCH] Avoid crashes when fringe bitmaps are defined in daemon mode * src/dispextern.h (gui_define_fringe_bitmap): Add prototype. (max_used_fringe_bitmap): Add declaration. * src/fringe.c (gui_define_fringe_bitmap): New function. * src/w32term.c (w32_draw_fringe_bitmap): * src/xterm.c (x_draw_fringe_bitmap) [USE_CAIRO]: Call 'gui_define_fringe_bitmap' if the terminal-specific bitmap data is not available when a fringe bitmap is about to be drawn. Don't try to draw a bitmap that is not known to fringe.c. (Bug#54183) --- src/dispextern.h | 3 +++ src/fringe.c | 17 +++++++++++++++++ src/w32term.c | 15 ++++++++++++++- src/xterm.c | 14 +++++++++++++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index bc5f7a52e08..65801596d5d 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3449,6 +3449,9 @@ bool update_window_fringes (struct window *, bool); void gui_init_fringe (struct redisplay_interface *); +extern int max_used_fringe_bitmap; +void gui_define_fringe_bitmap (struct frame *, int); + #ifdef HAVE_NTGUI void w32_reset_fringes (void); #endif diff --git a/src/fringe.c b/src/fringe.c index f857aedaf02..14148a67ab1 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -1802,6 +1802,23 @@ gui_init_fringe (struct redisplay_interface *rif) } } +/* Call frame F's specific define_fringe_bitmap method for a fringe + bitmap number N. Called by various *term.c functions when they + need to display a fringe bitmap whose terminal-specific data is not + available. */ +void +gui_define_fringe_bitmap (struct frame *f, int n) +{ + struct redisplay_interface *rif = FRAME_RIF (f); + + if (!rif || !rif->define_fringe_bitmap || n >= max_used_fringe_bitmap) + return; + + struct fringe_bitmap *fb = fringe_bitmaps[n]; + if (fb) + rif->define_fringe_bitmap (n, fb->bits, fb->height, fb->width); +} + #ifdef HAVE_NTGUI void w32_reset_fringes (void) diff --git a/src/w32term.c b/src/w32term.c index 6b41b1d324f..ae99d9948e6 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -777,12 +777,25 @@ w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row, w32_fill_area (f, hdc, face->background, p->bx, p->by, p->nx, p->ny); - if (p->which && p->which < max_fringe_bmp) + if (p->which + && p->which < max_fringe_bmp + && p->which < max_used_fringe_bitmap) { HBITMAP pixmap = fringe_bmp[p->which]; HDC compat_hdc; HANDLE horig_obj; + if (!fringe_bmp[p->which]) + { + /* This fringe bitmap is known to fringe.c, but lacks the + HBITMAP data which shadows that bitmap. This is typical + to define-fringe-bitmap being called when the selected + frame was not a GUI frame, for example, when packages + that define fringe bitmaps are loaded by a daemon Emacs. + Create the missing HBITMAP now. */ + gui_define_fringe_bitmap (f, p->which); + } + compat_hdc = CreateCompatibleDC (hdc); SaveDC (hdc); diff --git a/src/xterm.c b/src/xterm.c index 59413eafd48..9a8c3e9ad76 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1426,7 +1426,9 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring } #ifdef USE_CAIRO - if (p->which && p->which < max_fringe_bmp) + if (p->which + && p->which < max_fringe_bmp + && p->which < max_used_fringe_bitmap) { XGCValues gcv; @@ -1436,6 +1438,16 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring : f->output_data.x->cursor_pixel) : face->foreground)); XSetBackground (display, gc, face->background); + if (!fringe_bmp[p->which]) + { + /* This fringe bitmap is known to fringe.c, but lacks the + cairo_pattern_t pattern which shadows that bitmap. This + is typical to define-fringe-bitmap being called when the + selected frame was not a GUI frame, for example, when + packages that define fringe bitmaps are loaded by a + daemon Emacs. Create the missing pattern now. */ + gui_define_fringe_bitmap (f, p->which); + } x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh, p->wd, p->h, p->x, p->y, p->overlay_p); XSetForeground (display, gc, gcv.foreground); -- 2.39.2