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

             Bug #: 51455
           Summary: Possible uninitialized register use when array
                    subscript is unsigned
    Classification: Unclassified
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: frederik.dewee...@gmail.com


This happens on 4.4, 4.5 and 4.6, with and without strict aliasing.

The following C code:

======================
#include <string.h>

#define SIZE 128
int main(void)
{
    int buf[SIZE];
    char offsets[SIZE];
    int index = 13;
    int ret;
    int i;

    for (i = 0; i < SIZE; i++) {
        buf[i] = i;
        offsets[i] = (char)i;
    }
    asm volatile ("mov $0xfafafafafafafafa, %%rax" : : : "rax");
    asm volatile ("nop" : : : "memory");
    //ret = buf[offsets[index]];
        /* XXX: Unsigned subscript here */
    ret = buf[((unsigned char *)offsets)[index]];
    asm volatile ("nop" : : : "memory");
    return ret;
}
======================

Generates the following asm for the array access:

   0x0000000000400476 <+54>:    movabs $0xfafafafafafafafa,%rax
   0x0000000000400480 <+64>:    nop
   0x0000000000400481 <+65>:    movzbl 0x20d(%rsp),%eax
   0x0000000000400489 <+73>:    mov    (%rsp,%rax,4),%eax
   0x000000000040048c <+76>:    nop

Note how we init eax first and then use rax as an index.

On the other hand, if I remove the cast to 'unsigned char *' (commented in the
snippet above), I get:
   0x0000000000400476 <+54>:    movabs $0xfafafafafafafafa,%rax
   0x0000000000400480 <+64>:    nop
   0x0000000000400481 <+65>:    movsbq 0x20d(%rsp),%rax
   0x000000000040048a <+74>:    mov    (%rsp,%rax,4),%eax
   0x000000000040048d <+77>:    nop

Which initalizes the full rax register, as I would expect.


The questions I have are:
- shouldn't the full rax register be set in the 'unsigned char *' version as
well?
- is there any warranty that movzbl will zero eax's upper 4 bytes in the
'unsigned char *' version? I can't get the program to crash on the systems I
tested, and I would have expected they would, as AMD's docs don't mention the
zeroing of the upper 4 bytes.


Thanks,
Frederik

Reply via email to