]> code.delx.au - gnu-emacs/commitdiff
Fix segfaults due to using a stale face ID
authorPhilip <pipcet@gmail.com>
Sat, 5 Sep 2015 08:08:57 +0000 (11:08 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 5 Sep 2015 08:08:57 +0000 (11:08 +0300)
* 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

src/dispextern.h
src/xdisp.c
src/xfaces.c

index 37ebab04ddf465a072fed9167441366424b8313a..e5adeab0dc02fc8334f7c0e3ee4722fafedf1f33 100644 (file)
@@ -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 *);
 
index 9ff9f6ce399805f91873616d8c054aa839745935..82931b88e1c12c23ec2022f2d7b48ff5c4fce532 100644 (file)
@@ -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
index d89adca8c578064764a1ad79485422f0319c51c6..030324963814a2493dfd426857ed22ad9a19aba6 100644 (file)
@@ -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);