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