Fix segfaults due to using a stale face ID
* src/xdisp.c (forget_escape_and_glyphless_faces): New function. (display_echo_area_1, redisplay_internal): Call it to avoid reusing stale face IDs for 'escape-glyph' and 'glyphless-char' faces, which could case a segfault if the frame's face cache was freed since the last redisplay. (Bug#21394) * src/xfaces.c (free_realized_faces): Call forget_escape_and_glyphless_faces. * src/dispextern.h (forget_escape_and_glyphless_faces): Add prototype. Copyright-paperwork-exempt: yes
This commit is contained in:
parent
8a6260e1e1
commit
90937cbfe4
3 changed files with 21 additions and 4 deletions
|
@ -3245,6 +3245,7 @@ extern ptrdiff_t compute_display_string_end (ptrdiff_t,
|
|||
struct bidi_string_data *);
|
||||
extern void produce_stretch_glyph (struct it *);
|
||||
extern int merge_glyphless_glyph_face (struct it *);
|
||||
extern void forget_escape_and_glyphless_faces (void);
|
||||
|
||||
extern void get_font_ascent_descent (struct font *, int *, int *);
|
||||
|
||||
|
|
22
src/xdisp.c
22
src/xdisp.c
|
@ -6787,6 +6787,18 @@ merge_glyphless_glyph_face (struct it *it)
|
|||
return face_id;
|
||||
}
|
||||
|
||||
/* Forget the `escape-glyph' and `glyphless-char' faces. This should
|
||||
be called before redisplaying windows, and when the frame's face
|
||||
cache is freed. */
|
||||
void
|
||||
forget_escape_and_glyphless_faces (void)
|
||||
{
|
||||
last_escape_glyph_frame = NULL;
|
||||
last_escape_glyph_face_id = (1 << FACE_ID_BITS);
|
||||
last_glyphless_glyph_frame = NULL;
|
||||
last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
|
||||
}
|
||||
|
||||
/* Load IT's display element fields with information about the next
|
||||
display element from the current position of IT. Value is false if
|
||||
end of buffer (or C string) is reached. */
|
||||
|
@ -10673,6 +10685,11 @@ display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
|
|||
Lisp_Object window;
|
||||
struct text_pos start;
|
||||
|
||||
/* We are about to enter redisplay without going through
|
||||
redisplay_internal, so we need to forget these faces by hand
|
||||
here. */
|
||||
forget_escape_and_glyphless_faces ();
|
||||
|
||||
/* Do this before displaying, so that we have a large enough glyph
|
||||
matrix for the display. If we can't get enough space for the
|
||||
whole text, display the last N lines. That works by setting w->start. */
|
||||
|
@ -13326,10 +13343,7 @@ redisplay_internal (void)
|
|||
sw = w;
|
||||
|
||||
pending = false;
|
||||
last_escape_glyph_frame = NULL;
|
||||
last_escape_glyph_face_id = (1 << FACE_ID_BITS);
|
||||
last_glyphless_glyph_frame = NULL;
|
||||
last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
|
||||
forget_escape_and_glyphless_faces ();
|
||||
|
||||
/* If face_change, init_iterator will free all realized faces, which
|
||||
includes the faces referenced from current matrices. So, we
|
||||
|
|
|
@ -4173,6 +4173,8 @@ free_realized_faces (struct face_cache *c)
|
|||
c->faces_by_id[i] = NULL;
|
||||
}
|
||||
|
||||
/* Forget the escape-glyph and glyphless-char faces. */
|
||||
forget_escape_and_glyphless_faces ();
|
||||
c->used = 0;
|
||||
size = FACE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
|
||||
memset (c->buckets, 0, size);
|
||||
|
|
Loading…
Add table
Reference in a new issue