diff options
| author | Eli Zaretskii | 2020-12-10 17:10:06 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2020-12-10 17:10:06 +0200 |
| commit | 97c2bca729862ef5f50b03997e47b63b97b0d2c2 (patch) | |
| tree | 4e1679f014b17835cdd2fdfe5b9d157824e40ea3 | |
| parent | 6596b5541dd147749e2091953ac77bcd73c8d404 (diff) | |
| download | emacs-97c2bca729862ef5f50b03997e47b63b97b0d2c2.tar.gz emacs-97c2bca729862ef5f50b03997e47b63b97b0d2c2.zip | |
Avoid segfaults in pos_visible_p
* src/xdisp.c (pos_visible_p): Don't try accessing the glyphs
produced by iterator whose glyph_row was set to NULL; instead,
record the X coordinate before the display string when moving past
it, and use the recorded coordinate if needed. (Bug#45156)
| -rw-r--r-- | src/xdisp.c | 40 |
1 files changed, 18 insertions, 22 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index ed1d4761b95..689b87df421 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -1925,12 +1925,12 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, | |||
| 1925 | /* If it3_moved stays false after the 'while' loop | 1925 | /* If it3_moved stays false after the 'while' loop |
| 1926 | below, that means we already were at a newline | 1926 | below, that means we already were at a newline |
| 1927 | before the loop (e.g., the display string begins | 1927 | before the loop (e.g., the display string begins |
| 1928 | with a newline), so we don't need to (and cannot) | 1928 | with a newline), so we don't need to return to |
| 1929 | inspect the glyphs of it3.glyph_row, because | 1929 | the last position before the display string, |
| 1930 | PRODUCE_GLYPHS will not produce anything for a | 1930 | because PRODUCE_GLYPHS will not produce anything |
| 1931 | newline, and thus it3.glyph_row stays at its | 1931 | for a newline. */ |
| 1932 | stale content it got at top of the window. */ | ||
| 1933 | bool it3_moved = false; | 1932 | bool it3_moved = false; |
| 1933 | int top_x_before_string = it3.current_x; | ||
| 1934 | /* Finally, advance the iterator until we hit the | 1934 | /* Finally, advance the iterator until we hit the |
| 1935 | first display element whose character position is | 1935 | first display element whose character position is |
| 1936 | CHARPOS, or until the first newline from the | 1936 | CHARPOS, or until the first newline from the |
| @@ -1938,6 +1938,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, | |||
| 1938 | display line. */ | 1938 | display line. */ |
| 1939 | while (get_next_display_element (&it3)) | 1939 | while (get_next_display_element (&it3)) |
| 1940 | { | 1940 | { |
| 1941 | if (!EQ (it3.object, string)) | ||
| 1942 | top_x_before_string = it3.current_x; | ||
| 1941 | PRODUCE_GLYPHS (&it3); | 1943 | PRODUCE_GLYPHS (&it3); |
| 1942 | if (IT_CHARPOS (it3) == charpos | 1944 | if (IT_CHARPOS (it3) == charpos |
| 1943 | || ITERATOR_AT_END_OF_LINE_P (&it3)) | 1945 | || ITERATOR_AT_END_OF_LINE_P (&it3)) |
| @@ -1952,32 +1954,26 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, | |||
| 1952 | if (!it3.line_number_produced_p) | 1954 | if (!it3.line_number_produced_p) |
| 1953 | { | 1955 | { |
| 1954 | if (it3.lnum_pixel_width > 0) | 1956 | if (it3.lnum_pixel_width > 0) |
| 1955 | top_x += it3.lnum_pixel_width; | 1957 | { |
| 1958 | top_x += it3.lnum_pixel_width; | ||
| 1959 | top_x_before_string += it3.lnum_pixel_width; | ||
| 1960 | } | ||
| 1956 | else if (it.line_number_produced_p) | 1961 | else if (it.line_number_produced_p) |
| 1957 | top_x += it.lnum_pixel_width; | 1962 | { |
| 1963 | top_x += it.lnum_pixel_width; | ||
| 1964 | top_x_before_string += it3.lnum_pixel_width; | ||
| 1965 | } | ||
| 1958 | } | 1966 | } |
| 1959 | /* Normally, we would exit the above loop because we | 1967 | /* Normally, we would exit the above loop because we |
| 1960 | found the display element whose character | 1968 | found the display element whose character |
| 1961 | position is CHARPOS. For the contingency that we | 1969 | position is CHARPOS. For the contingency that we |
| 1962 | didn't, and stopped at the first newline from the | 1970 | didn't, and stopped at the first newline from the |
| 1963 | display string, move back over the glyphs | 1971 | display string, reset top_x to the coordinate of |
| 1964 | produced from the string, until we find the | 1972 | the rightmost glyph not from the string. */ |
| 1965 | rightmost glyph not from the string. */ | ||
| 1966 | if (it3_moved | 1973 | if (it3_moved |
| 1967 | && newline_in_string | 1974 | && newline_in_string |
| 1968 | && IT_CHARPOS (it3) != charpos && EQ (it3.object, string)) | 1975 | && IT_CHARPOS (it3) != charpos && EQ (it3.object, string)) |
| 1969 | { | 1976 | top_x = top_x_before_string; |
| 1970 | struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA] | ||
| 1971 | + it3.glyph_row->used[TEXT_AREA]; | ||
| 1972 | |||
| 1973 | while (EQ ((g - 1)->object, string)) | ||
| 1974 | { | ||
| 1975 | --g; | ||
| 1976 | top_x -= g->pixel_width; | ||
| 1977 | } | ||
| 1978 | eassert (g < it3.glyph_row->glyphs[TEXT_AREA] | ||
| 1979 | + it3.glyph_row->used[TEXT_AREA]); | ||
| 1980 | } | ||
| 1981 | } | 1977 | } |
| 1982 | } | 1978 | } |
| 1983 | 1979 | ||