From 08fff70c6eab76f935d6827e3fd030ec40457f1d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 12 Aug 2011 14:19:44 +0300 Subject: [PATCH] Fix bug #9284 with line/wrap-prefix property on display strings. src/xdisp.c (iterate_out_of_display_property): xassert that IT->position is set to within IT->object's boundaries. Break from the loop as soon as EOB is reached; avoids infloops in redisplay when IT->position is set up wrongly due to some bug. Set IT->current to match the bidi iterator unconditionally. (push_display_prop): Allow GET_FROM_STRING as IT->method on entry; avoids crashes when line/wrap-prefix is set on a display string. Force push_it to save on the stack the current buffer/string position, to be restored by pop_it. Fix flags in the iterator structure wrt the object coming from a display property, as `line-prefix' and `wrap-prefix' are not ``replacing'' properties. --- src/ChangeLog | 14 ++++++++++++++ src/xdisp.c | 43 +++++++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index af9586037d7..5c65159a841 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2011-08-12 Eli Zaretskii + + * xdisp.c (iterate_out_of_display_property): xassert that + IT->position is set to within IT->object's boundaries. Break from + the loop as soon as EOB is reached; avoids infloops in redisplay + when IT->position is set up wrongly due to some bug. Set + IT->current to match the bidi iterator unconditionally. + (push_display_prop): Allow GET_FROM_STRING as IT->method on + entry. Force push_it to save on the stack the current + buffer/string position, to be restored by pop_it. Fix flags in + the iterator structure wrt the object coming from a display + property, as `line-prefix' and `wrap-prefix' are not ``replacing'' + properties. (Bug#9284) + 2011-08-09 Andreas Schwab * fontset.c (fontset_get_font_group): Add proper type checks. diff --git a/src/xdisp.c b/src/xdisp.c index 1437aafef39..a3bdcbdf4c6 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5326,6 +5326,8 @@ iterate_out_of_display_property (struct it *it) EMACS_INT eob = (buffer_p ? ZV : it->end_charpos); EMACS_INT bob = (buffer_p ? BEGV : 0); + xassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob); + /* Maybe initialize paragraph direction. If we are at the beginning of a new paragraph, next_element_from_buffer may not have a chance to do that. */ @@ -5334,7 +5336,8 @@ iterate_out_of_display_property (struct it *it) /* prev_stop can be zero, so check against BEGV as well. */ while (it->bidi_it.charpos >= bob && it->prev_stop <= it->bidi_it.charpos - && it->bidi_it.charpos < CHARPOS (it->position)) + && it->bidi_it.charpos < CHARPOS (it->position) + && it->bidi_it.charpos < eob) bidi_move_to_visually_next (&it->bidi_it); /* Record the stop_pos we just crossed, for when we cross it back, maybe. */ @@ -5343,14 +5346,11 @@ iterate_out_of_display_property (struct it *it) /* If we ended up not where pop_it put us, resync IT's positional members with the bidi iterator. */ if (it->bidi_it.charpos != CHARPOS (it->position)) - { - SET_TEXT_POS (it->position, - it->bidi_it.charpos, it->bidi_it.bytepos); - if (buffer_p) - it->current.pos = it->position; - else - it->current.string_pos = it->position; - } + SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos); + if (buffer_p) + it->current.pos = it->position; + else + it->current.string_pos = it->position; } /* Restore IT's settings from IT->stack. Called, for example, when no @@ -18056,16 +18056,25 @@ cursor_row_p (struct glyph_row *row) -/* Push the display property PROP so that it will be rendered at the - current position in IT. Return 1 if PROP was successfully pushed, - 0 otherwise. */ +/* Push the property PROP so that it will be rendered at the current + position in IT. Return 1 if PROP was successfully pushed, 0 + otherwise. Called from handle_line_prefix to handle the + `line-prefix' and `wrap-prefix' properties. */ static int push_display_prop (struct it *it, Lisp_Object prop) { - xassert (it->method == GET_FROM_BUFFER); + struct text_pos pos = + (it->method == GET_FROM_STRING) ? it->current.string_pos : it->current.pos; - push_it (it, NULL); + xassert (it->method == GET_FROM_BUFFER + || it->method == GET_FROM_STRING); + + /* We need to save the current buffer/string position, so it will be + restored by pop_it, because iterate_out_of_display_property + depends on that being set correctly, but some situations leave + it->position not yet set when this function is called. */ + push_it (it, &pos); if (STRINGP (prop)) { @@ -18084,11 +18093,9 @@ push_display_prop (struct it *it, Lisp_Object prop) it->stop_charpos = 0; it->prev_stop = 0; it->base_level_stop = 0; - it->string_from_display_prop_p = 1; - it->from_disp_prop_p = 1; /* Force paragraph direction to be that of the parent - buffer. */ + buffer/string. */ if (it->bidi_p && it->bidi_it.paragraph_dir == R2L) it->paragraph_embedding = it->bidi_it.paragraph_dir; else @@ -18101,7 +18108,7 @@ push_display_prop (struct it *it, Lisp_Object prop) it->bidi_it.string.s = NULL; it->bidi_it.string.schars = it->end_charpos; it->bidi_it.string.bufpos = IT_CHARPOS (*it); - it->bidi_it.string.from_disp_str = 1; + it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; it->bidi_it.string.unibyte = !it->multibyte_p; bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); } -- 2.11.4.GIT