From f149cf2d6fbd9f864696620f94187e373812c919 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Mon, 19 Aug 2024 17:38:47 -0700 Subject: [PATCH] Fix bad interactions with 'min-width' display spec and replacement strings Previously, when iterating over overlays or replacement strings from a display spec, we would pass the string and the buffer position to 'display_min_width', which would use those values to try to get the display property. However, the buffer position is very likely out of bounds for the replacement string! (bug#72721) * src/xdisp.c (get_display_property): Rename BUFPOS to CHARPOS; OBJECT might not be a buffer. (display_min_width): Add CHARPOS argument and update callers. This helps us distinguish when we're still examining a replacement string. Simplify implementation to use a non-nil 'min_width_property' to determine what to do; since we can't nest 'min-width', this should be safe. It also lets us insert space into the buffer at the right time. --- src/xdisp.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index 30771a1c83d..1fb9a436b8c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5633,15 +5633,15 @@ find_display_property (Lisp_Object disp, Lisp_Object prop) } static Lisp_Object -get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object) +get_display_property (ptrdiff_t charpos, Lisp_Object prop, Lisp_Object object) { - return find_display_property (Fget_text_property (make_fixnum (bufpos), + return find_display_property (Fget_text_property (make_fixnum (charpos), Qdisplay, object), prop); } static void -display_min_width (struct it *it, ptrdiff_t bufpos, +display_min_width (struct it *it, ptrdiff_t bufpos, ptrdiff_t charpos, Lisp_Object object, Lisp_Object width_spec) { /* We're being called at the end of the `min-width' sequence, @@ -5656,11 +5656,8 @@ display_min_width (struct it *it, ptrdiff_t bufpos, if ((bufpos == 0 && !EQ (it->min_width_property, get_display_property (0, Qmin_width, object))) - /* In a buffer -- check that we're really right after the - sequence of characters covered by this `min-width'. */ - || (bufpos > BEGV - && EQ (it->min_width_property, - get_display_property (bufpos - 1, Qmin_width, object)))) + /* In a buffer, and not working with a replacement string. */ + || (bufpos > BEGV && charpos > 0)) { Lisp_Object w = Qnil; double width; @@ -5705,21 +5702,13 @@ display_min_width (struct it *it, ptrdiff_t bufpos, /* We're at the start of a `min-width' sequence -- record the position and the property, so that we can later see if we're at the end. */ - if (CONSP (width_spec)) + if (CONSP (width_spec) + /* Make sure we're not actively processing a `min-width' sequence. + We can't currently nest them. */ + && NILP (it->min_width_property)) { - if (bufpos == BEGV - /* Mode line (see above). */ - || (bufpos == 0 - && !EQ (it->min_width_property, - get_display_property (0, Qmin_width, object))) - /* Buffer. */ - || (bufpos > BEGV - && !EQ (width_spec, - get_display_property (bufpos - 1, Qmin_width, object)))) - { - it->min_width_property = width_spec; - it->min_width_start = it->current_x; - } + it->min_width_property = width_spec; + it->min_width_start = it->current_x; } } @@ -5795,10 +5784,10 @@ handle_display_prop (struct it *it) if (!STRINGP (it->string)) object = it->w->contents; - /* Handle min-width ends. */ + /* Handle min-width ends. */ if (!NILP (it->min_width_property) && NILP (find_display_property (propval, Qmin_width))) - display_min_width (it, bufpos, object, Qnil); + display_min_width (it, bufpos, CHARPOS (*position), object, Qnil); if (NILP (propval)) return HANDLED_NORMALLY; @@ -6099,7 +6088,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, && CONSP (XCAR (XCDR (spec)))) { if (it) - display_min_width (it, bufpos, object, XCAR (XCDR (spec))); + display_min_width (it, bufpos, CHARPOS (*position), object, XCAR (XCDR (spec))); return 0; } @@ -29235,7 +29224,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st { Lisp_Object min_width = plist_get (display, Qmin_width); if (!NILP (min_width)) - display_min_width (it, 0, face_string, min_width); + display_min_width (it, 0, 0, face_string, min_width); } } } -- 2.25.1