bug#81568: 32.0.50; crash in Fnext_single_property_change

andrei.elkin--- via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <[email protected]>
Newsgroups gmane.emacs.bugs
Organization Home sweet home
Message-ID <87mruwh8af.fsf@quad>
Eli Zaretskii <[email protected]> writes:

>> From: [email protected]
>> Cc: [email protected]
>> Date: Sat, 08 Aug 2026 15:32:30 +0300
>> 
>> > Please try to figure out which data caused the segfault.  The code
>> > where it happens is
>> >
>> >   next = next_interval (i);
>> >   while (next
>> > 	 && EQ (here_val, textget (next->plist, prop))
>> > 	 && (NILP (limit) || next->position < XFIXNUM (limit)))
>> >     next = next_interval (next);
>> >
>> > and according to the backtrace, the value of 'next' looks okay at
>> > first sight.
>> 
>> We have a cycle, that is
>> 
>>    next == i
>
> On what source line does this happen in the above snippet?

I queried the two having the execution point where the crash occurred.
Here

  (gdb) x/20i $pc - 40
   0x555555938b84 <Fnext_single_property_change+389>:   (bad) 0x48(%rsp,%rdx,2)
   0x555555938b88 <Fnext_single_property_change+393>:   mov    -0x40(%rbp),%edx
   0x555555938b8b <Fnext_single_property_change+396>:   mov    0x30(%rbx),%rax
   0x555555938b8f <Fnext_single_property_change+400>:   mov    %rdx,%rsi
   0x555555938b92 <Fnext_single_property_change+403>:   mov    %rax,%rdi
   0x555555938b95 <Fnext_single_property_change+406>:   call   0x5555559329d3 <textget>
   0x555555938b9a <Fnext_single_property_change+411>:   mov    %rax,%rdx
   0x555555938b9d <Fnext_single_property_change+414>:   mov    -0x28(%rbp),%rax
   0x555555938ba1 <Fnext_single_property_change+418>:   mov    %rdx,%rsi
   0x555555938ba4 <Fnext_single_property_change+421>:   mov    %rax,%rdi
   0x555555938ba7 <Fnext_single_property_change+424>:   call   0x555555935622 <EQ>
=> 0x555555938bac <Fnext_single_property_change+429>:   test   %al,%al
   0x555555938bae <Fnext_single_property_change+431>:   je     0x555555938bdb <Fnext_single_property_change+476>
   0x555555938bb0 <Fnext_single_property_change+433>:   mov    -0x50(%rbp),%rax
   0x555555938bb4 <Fnext_single_property_change+437>:   mov    %rax,%r12
   0x555555938bb7 <Fnext_single_property_change+440>:   mov    $0x0,%edi
   0x555555938bbc <Fnext_single_property_change+445>:   call   0x5555559354eb <builtin_lisp_symbol>
   0x555555938bc1 <Fnext_single_property_change+450>:   cmp    %rax,%r12
   0x555555938bc4 <Fnext_single_property_change+453>:   je     0x555555938b77 <Fnext_single_property_change+376>
   0x555555938bc6 <Fnext_single_property_change+455>:   mov    0x8(%rbx),%r12 

>
> And how can a cycle cause a segfault?  It could cause an infloop, but
> that's not what you see.

I have no clue. AI speculated on an OS iterruption

  In the GDB register dump, the eflags register state is highly revealing:
  eflags         0x10246             [ PF ZF IF RF ]

  The presence of the RF (Resume Flag) is critical. The CPU and kernel use the Resume Flag to manage instruction restarts when returning from interrupts, exceptions, or signal handlers. Finding RF set on an instruction that cannot natively page-fault strongly indicates that this instruction was the interrupted execution site, not the faulting execution site.



>
>>    (gdb) p i
>>    $14 = (INTERVAL) 0x55557a555b40
>>    (gdb) p next
>>    $15 = (INTERVAL) 0x55557a555b40
>> 
>> Note `next= ...` initialization
>>    (gdb) p next_interval (i)
>>    $16 = (struct interval *) 0x55557a555b08
>> 
>> is not of `i` pointer.
>
> What do you mean by "is not of `i` pointer"?
>
> INTERVAL is the same as 'struct interval *', because of this:
>
>   typedef struct interval *INTERVAL;

I meant to point to  the initial assignment to
   next = next_interval (i)
is different from i, so the loop must've spun for some time.


>
>> Having gdb session I tried to reproduce the cycle, only to interrupt
>> that in few
>> seconds when the loop count reached some large value
>> 
>>    (gdb) set $next=$16
>>    (gdb) while i != $next
>>    >set $next=next_interval ($next)
>>    >set $cnt=$cnt+1
>>    >end
>>    ^CQuit
>>    (gdb) p $cnt
>>    $18 = 46189
>
> Why does it matter?

Perhaps naively but I expected to reach $next == i, starting from i.
But I did not succeed.
Why?
I don't know how many nodes the interval tree may have.
Is it per buffer?
Then 46189 could be too large for being reasonable..

Can we suspect here a broken iterval tree?
When not what can validate its consistency?


>
> I'm still confused regarding which part of the code above segfaults,
> and what is the problematic data which causes that.

I hope you can look into

   eflags         0x10246             [ PF ZF IF RF ]

and make sense of AI's speculation I quoted.

>
> Thanks.

Cheers,

/ndrei
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.