http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59409

--- Comment #14 from H.J. Lu <hjl.tools at gmail dot com> ---
(In reply to H.J. Lu from comment #13)
> loop in Perl_pp_aassign is miscompiled:
> 
>   44098a:       e8 91 38 05 00          callq  494220 <Perl_sv_mortalcopy>
>   44098f:       67 89 03                mov    %eax,(%ebx)
>   440992:       83 c3 04                add    $0x4,%ebx
>   440995:       67 44 8b 1b             mov    (%ebx),%r11d
>   440999:       45 85 db                test   %r11d,%r11d
>   44099c:       74 12                   je     4409b0 <Perl_pp_aassign+0x1c0>
>   44099e:       44 89 df                mov    %r11d,%edi
> 
> $r11d has invalid memory address.
> 
>   4409a1:       c6 05 65 fc 2c 00 00    movb   $0x0,0x2cfc65(%rip)        #
> 71060d <PL_tainted>
>   4409a8:       e8 73 38 05 00          callq  494220 <Perl_sv_mortalcopy>

Loop is

        for (relem = firstrelem; relem <= p; relem++) {
            /*SUPPRESS 560*/
            if (sv = *relem) {
                TAINT_NOT;      /* Each item is independent */
                *relem = sv_mortalcopy(sv);
            }

It was unrolled into

sv = *relem
TAINT_NOT
eax = Perl_sv_mortalcopy (sv)
*relem = eax
eax += 4;
sv = *(SV **) eax
TAINT_NOT
eax = Perl_sv_mortalcopy (sv)

I don't see how "eax += 4" can be correct.  Return from
Perl_sv_mortalcopy is unrelated to relem.

Reply via email to