Subject: Re: bug#77065: 31.0.50; Infinite loop in move_it_to

From: Yifan Zhu <[email-masked]>
Date: Mon, 17 Mar 2025 08:22:28 -0700

On 3/17/25 8:11 AM, Eli Zaretskii wrote:
>> Date: Mon, 17 Mar 2025 07:58:41 -0700
>> Cc: [email-masked]
>> From: Yifan Zhu <[email-masked]>
>>
>>   Thanks, but I don't have access to a system where these prerequisites
>> can be met.  So either someone can reproduce this, debug the problem,
>> and describe the reason for the loop, or I'd need to ask you to do it,
>> if possible.  Or, if you can show a recipe for reproducing the problem
>> without installing LaTeX and xenops, I could try reproducing this on
>> the systems to which I have access.
>>
>> I suspect that having (multiple) images inline might be the cause of the issue -- do you have any suggestions
>> on how to recreate this in vanilla emacs?
> Try to write some simple Lisp which arranges for a buffer to have the
> same images in the same positions in the buffer.

Thanks, will try.

>>   Can you step in GDB through one iteration of that
>> loop and show the values of variables which cause Emacs never to exit
>> the loop?
>>
>> I am not sure which variables I should show, as I am having some trouble understanding the exit conditions
>> of that infinite loop. Basically `move_it_in_display_line_to` always returns `MOVE_LINE_CONTINUED`, and
>> below is one iteration of stepping through the loop:
>>
>> 10947          switch (skip)
>> 10990          max_current_x = it->last_visible_x;
>> 10995          if (it->c == '\t')
>> 11030            it->continuation_lines_width += it->current_x;
>> 11031          break;
>> 11038          it->current_x = line_start_x;
>> 11039          it->wrap_prefix_width = 0;
>> 11040          line_start_x = 0;
>> 11041          it->hpos = 0;
>> 11042          it->line_number_produced_p = false;
>> 11043          it->current_y += it->max_ascent + it->max_descent;
>> 11044          ++it->vpos;
>> 11045          last_height = it->max_ascent + it->max_descent;
>> 11046          it->max_ascent = it->max_descent = 0;
>> 10759          if (op & MOVE_TO_VPOS)
>> 10803          else if (op & MOVE_TO_Y)
>> 10932          else if (BUFFERP (it->object)
>> 10933               && (it->method == GET_FROM_BUFFER
>> 10934               || it->method == GET_FROM_STRETCH)
>> 10945        skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
>> 10947          switch (skip)
> Thanks, but I also need to see at least the values of it->current.
> Does the position there never change? does it oscillate back and
> forth? is it perhaps stuck at ZV (the EOB position)? something else?

Its value never changes during the execution of move_it_to. It is stuck at

1: it->current = {
   pos = {
     charpos = 88,
     bytepos = 88
   },
   overlay_string_index = -1,
   string_pos = {
     charpos = -1,
     bytepos = -1
   },
   dpvec_index = -1
}

(gdb) p it->end_charpos
$27 = 333

(gdb) p ZV
$28 = 333

Doesn't seem to be the ZV.