diff options
| author | Dmitry Antipov | 2014-03-03 12:27:58 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2014-03-03 12:27:58 +0400 |
| commit | 19dae293f9fecea07c91440f0a33076c54d39b49 (patch) | |
| tree | e2ef81c52b8c2dc8ffad510110f3bc71b2b3524f /src | |
| parent | 8c1c761122b7472617c82fd00c949df52260c903 (diff) | |
| download | emacs-19dae293f9fecea07c91440f0a33076c54d39b49.tar.gz emacs-19dae293f9fecea07c91440f0a33076c54d39b49.zip | |
Avoid crashes when X fonts are erroneously freed on reused X
'Display *' connection data (Bug#16069). Note that X font
resources still may be leaked, but currently there is no way
to completely avoid it.
* xterm.h (struct x_display_info): New member x_id. Add comments.
* xterm.c (x_display_id): New variable.
(x_term_init): Assign identifier to each opened X connection.
* xfont.c (struct xfont): New member x_display_id.
(xfont_open): Initialize it with frame's display id.
(xfont_close): Check whether font's display id matches the one
recorded for the given display. Adjust comment.
* xftfont.c (struct xftfont_info):
(xftfont_open, xftfont_close): Exactly as above with xfont stuff.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 14 | ||||
| -rw-r--r-- | src/xfont.c | 14 | ||||
| -rw-r--r-- | src/xftfont.c | 6 | ||||
| -rw-r--r-- | src/xterm.c | 5 | ||||
| -rw-r--r-- | src/xterm.h | 4 |
5 files changed, 40 insertions, 3 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 280077c3844..7bc69b2894e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -6,6 +6,20 @@ | |||
| 6 | (Fframe_font_cache) [FONT_DEBUG]: New function. | 6 | (Fframe_font_cache) [FONT_DEBUG]: New function. |
| 7 | (syms_of_font) [FONT_DEBUG]: Defsubr it. | 7 | (syms_of_font) [FONT_DEBUG]: Defsubr it. |
| 8 | 8 | ||
| 9 | Avoid crashes when X fonts are erroneously freed on reused X | ||
| 10 | 'Display *' connection data (Bug#16069). Note that X font | ||
| 11 | resources still may be leaked, but currently there is no way | ||
| 12 | to completely avoid it. | ||
| 13 | * xterm.h (struct x_display_info): New member x_id. Add comments. | ||
| 14 | * xterm.c (x_display_id): New variable. | ||
| 15 | (x_term_init): Assign identifier to each opened X connection. | ||
| 16 | * xfont.c (struct xfont): New member x_display_id. | ||
| 17 | (xfont_open): Initialize it with frame's display id. | ||
| 18 | (xfont_close): Check whether font's display id matches the one | ||
| 19 | recorded for the given display. Adjust comment. | ||
| 20 | * xftfont.c (struct xftfont_info): | ||
| 21 | (xftfont_open, xftfont_close): Exactly as above with xfont stuff. | ||
| 22 | |||
| 9 | 2014-03-01 Martin Rudalics <rudalics@gmx.at> | 23 | 2014-03-01 Martin Rudalics <rudalics@gmx.at> |
| 10 | 24 | ||
| 11 | Consider Vother_window_scroll_buffer valid iff it's a live buffer. | 25 | Consider Vother_window_scroll_buffer valid iff it's a live buffer. |
diff --git a/src/xfont.c b/src/xfont.c index 3295a62bbb0..525f00031c5 100644 --- a/src/xfont.c +++ b/src/xfont.c | |||
| @@ -42,6 +42,7 @@ struct xfont_info | |||
| 42 | struct font font; | 42 | struct font font; |
| 43 | Display *display; | 43 | Display *display; |
| 44 | XFontStruct *xfont; | 44 | XFontStruct *xfont; |
| 45 | unsigned x_display_id; | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | /* Prototypes of support functions. */ | 48 | /* Prototypes of support functions. */ |
| @@ -808,6 +809,7 @@ xfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 808 | font = XFONT_OBJECT (font_object); | 809 | font = XFONT_OBJECT (font_object); |
| 809 | ((struct xfont_info *) font)->xfont = xfont; | 810 | ((struct xfont_info *) font)->xfont = xfont; |
| 810 | ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f); | 811 | ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f); |
| 812 | ((struct xfont_info *) font)->x_display_id = FRAME_DISPLAY_INFO (f)->x_id; | ||
| 811 | font->pixel_size = pixel_size; | 813 | font->pixel_size = pixel_size; |
| 812 | font->driver = &xfont_driver; | 814 | font->driver = &xfont_driver; |
| 813 | font->encoding_charset = encoding->id; | 815 | font->encoding_charset = encoding->id; |
| @@ -892,12 +894,20 @@ xfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 892 | static void | 894 | static void |
| 893 | xfont_close (struct font *font) | 895 | xfont_close (struct font *font) |
| 894 | { | 896 | { |
| 897 | struct x_display_info *xdi; | ||
| 895 | struct xfont_info *xfi = (struct xfont_info *) font; | 898 | struct xfont_info *xfi = (struct xfont_info *) font; |
| 896 | 899 | ||
| 897 | /* This function may be called from GC when X connection is gone | 900 | /* This function may be called from GC when X connection is gone |
| 898 | (Bug#16093), and an attempt to free font resources on invalid | 901 | (Bug#16093), and an attempt to free font resources on invalid |
| 899 | display may lead to X protocol errors or segfaults. */ | 902 | display may lead to X protocol errors or segfaults. Moreover, |
| 900 | if (xfi->xfont && x_display_info_for_display (xfi->display)) | 903 | the memory referenced by 'Display *' pointer may be reused for |
| 904 | the logically different X connection after the previous display | ||
| 905 | connection was closed. That's why we also check whether font's | ||
| 906 | ID matches the one recorded in x_display_info for this display. | ||
| 907 | See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16069. */ | ||
| 908 | if (xfi->xfont | ||
| 909 | && ((xdi = x_display_info_for_display (xfi->display)) | ||
| 910 | && xfi->x_display_id == xdi->x_id)) | ||
| 901 | { | 911 | { |
| 902 | block_input (); | 912 | block_input (); |
| 903 | XFreeFont (xfi->display, xfi->xfont); | 913 | XFreeFont (xfi->display, xfi->xfont); |
diff --git a/src/xftfont.c b/src/xftfont.c index 32816b97f23..18c180f906a 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -59,6 +59,7 @@ struct xftfont_info | |||
| 59 | FT_Matrix matrix; | 59 | FT_Matrix matrix; |
| 60 | Display *display; | 60 | Display *display; |
| 61 | XftFont *xftfont; | 61 | XftFont *xftfont; |
| 62 | unsigned x_display_id; | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | /* Structure pointed by (struct face *)->extra */ | 65 | /* Structure pointed by (struct face *)->extra */ |
| @@ -372,6 +373,7 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 372 | xftfont_info = (struct xftfont_info *) font; | 373 | xftfont_info = (struct xftfont_info *) font; |
| 373 | xftfont_info->display = display; | 374 | xftfont_info->display = display; |
| 374 | xftfont_info->xftfont = xftfont; | 375 | xftfont_info->xftfont = xftfont; |
| 376 | xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id; | ||
| 375 | /* This means that there's no need of transformation. */ | 377 | /* This means that there's no need of transformation. */ |
| 376 | xftfont_info->matrix.xx = 0; | 378 | xftfont_info->matrix.xx = 0; |
| 377 | if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix) | 379 | if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix) |
| @@ -481,6 +483,7 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 481 | static void | 483 | static void |
| 482 | xftfont_close (struct font *font) | 484 | xftfont_close (struct font *font) |
| 483 | { | 485 | { |
| 486 | struct x_display_info *xdi; | ||
| 484 | struct xftfont_info *xftfont_info = (struct xftfont_info *) font; | 487 | struct xftfont_info *xftfont_info = (struct xftfont_info *) font; |
| 485 | 488 | ||
| 486 | #ifdef HAVE_LIBOTF | 489 | #ifdef HAVE_LIBOTF |
| @@ -493,7 +496,8 @@ xftfont_close (struct font *font) | |||
| 493 | 496 | ||
| 494 | /* See comment in xfont_close. */ | 497 | /* See comment in xfont_close. */ |
| 495 | if (xftfont_info->xftfont | 498 | if (xftfont_info->xftfont |
| 496 | && x_display_info_for_display (xftfont_info->display)) | 499 | && ((xdi = x_display_info_for_display (xftfont_info->display)) |
| 500 | && xftfont_info->x_display_id == xdi->x_id)) | ||
| 497 | { | 501 | { |
| 498 | block_input (); | 502 | block_input (); |
| 499 | XftUnlockFace (xftfont_info->xftfont); | 503 | XftUnlockFace (xftfont_info->xftfont); |
diff --git a/src/xterm.c b/src/xterm.c index e1873127276..f06225002a7 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -9679,6 +9679,10 @@ my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, | |||
| 9679 | } | 9679 | } |
| 9680 | #endif | 9680 | #endif |
| 9681 | 9681 | ||
| 9682 | /* Current X display connection identifier. Incremented for each next | ||
| 9683 | connection established. */ | ||
| 9684 | static unsigned x_display_id; | ||
| 9685 | |||
| 9682 | /* Open a connection to X display DISPLAY_NAME, and return | 9686 | /* Open a connection to X display DISPLAY_NAME, and return |
| 9683 | the structure that describes the open display. | 9687 | the structure that describes the open display. |
| 9684 | If we cannot contact the display, return null. */ | 9688 | If we cannot contact the display, return null. */ |
| @@ -9896,6 +9900,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 9896 | lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@"; | 9900 | lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@"; |
| 9897 | if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name)) | 9901 | if (lim - SBYTES (Vinvocation_name) < SBYTES (Vsystem_name)) |
| 9898 | memory_full (SIZE_MAX); | 9902 | memory_full (SIZE_MAX); |
| 9903 | dpyinfo->x_id = ++x_display_id; | ||
| 9899 | dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name) | 9904 | dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name) |
| 9900 | + SBYTES (Vsystem_name) + 2); | 9905 | + SBYTES (Vsystem_name) + 2); |
| 9901 | strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"), | 9906 | strcat (strcat (strcpy (dpyinfo->x_id_name, SSDATA (Vinvocation_name)), "@"), |
diff --git a/src/xterm.h b/src/xterm.h index 3e79d46702c..50df88cb592 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -198,6 +198,10 @@ struct x_display_info | |||
| 198 | mouse-face. */ | 198 | mouse-face. */ |
| 199 | Mouse_HLInfo mouse_highlight; | 199 | Mouse_HLInfo mouse_highlight; |
| 200 | 200 | ||
| 201 | /* Logical identifier of this display. */ | ||
| 202 | unsigned x_id; | ||
| 203 | |||
| 204 | /* Default name for all frames on this display. */ | ||
| 201 | char *x_id_name; | 205 | char *x_id_name; |
| 202 | 206 | ||
| 203 | /* The number of fonts opened for this display. */ | 207 | /* The number of fonts opened for this display. */ |