https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64242

--- Comment #27 from Wilco <wilco at gcc dot gnu.org> ---
(In reply to dave.anglin from comment #26)
> On 2019-06-10 9:51 a.m., wilco at gcc dot gnu.org wrote:
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64242
> >
> > --- Comment #25 from Wilco <wilco at gcc dot gnu.org> ---
> > I believe this is now fixed for generic code - however targets which 
> > implement
> > the nonlocal_goto expander (eg. pa, sparc, vax) need similar fixes in their
> > backends.
> >
> The test no longer fails on pa.  We need a test that demonstrates the
> problem in the current
> pa expander.

It allocates the buf variables at exactly the same offset in both frames, so
the code below accidentally reads the right values from the wrong address:

broken_longjmp:
        .PROC
        .CALLINFO FRAME=192,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
        .ENTRY
        copy %r3,%r1
        stw %r2,-20(%r30)
        copy %r30,%r3
        stwm %r1,192(%r30)
        copy %r26,%r25
        ldi 20,%r24
        bl memcpy,%r2
        ldo 8(%r3),%r26
        ldw 8(%r3),%r28  -> load frame pointer of parent function
        ldo -8(%r28),%r3 -> set hard_frame_pointer
        ldw 16(%r3),%r30 -> use wrong frame pointer to read stack pointer
        ldw 12(%r3),%r1  -> use wrong frame pointer to read return address
        be,n 0(%sr4,%r1)

Given there are many possible stack layouts, the easiest option would be to
clear the input buffer so it will jump to a null pointer. Eg.

__attribute ((noinline)) void
broken_longjmp (void *p)
{
  void *buf[32];
  __builtin_memcpy (buf, p, 5 * sizeof (void*));
  __builtin_memset (p, 0, 5 * sizeof (void*));
  /* Corrupts stack pointer...  */
  __builtin_longjmp (buf, 1);
}

Reply via email to