https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104607
Bug ID: 104607 Summary: Struct padding not initialized when all members are provided initializers Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: pascal_cuoq at hotmail dot com Target Milestone: --- In the GCC versions available as 11.2 and as “trunk” (as of this writing) on Compiler Explorer, the following C code is translated to the following X86-64 assembly, with options “-O2 -std=c17” CE link: https://gcc.godbolt.org/z/4oeh6d7vY void g(void*); int f(void) { struct s { char c; long long m64;} s12 = {1,2}, s1 = {1}; g(&s1); g(&s12); } f: subq $40, %rsp pxor %xmm0, %xmm0 leaq 16(%rsp), %rdi movaps %xmm0, 16(%rsp) movb $1, (%rsp) movq $2, 8(%rsp) movb $1, 16(%rsp) call g movq %rsp, %rdi call g addq $40, %rsp ret Please note that GCC initializes all of s1 with “movaps %xmm0, 16(%rsp)” and that initializing only s1.m64 to 0 in addition to initializing s1.c to 1 would have resulted in fewer, shorter instructions. However, s12 is not initialized this way, and indeed the padding of s12 is not initialized at all. The requirement to initialize padding is a change that was introduced between C99 and C11. The relevant clauses are in C99: https://port70.net/~nsz/c/c99/n1256.html#6.7.8p10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then: if it has pointer type, it is initialized to a null pointer; if it has arithmetic type, it is initialized to (positive or unsigned) zero; if it is an aggregate, every member is initialized (recursively) according to these rules; if it is a union, the first named member is initialized (recursively) according to these rules. https://port70.net/~nsz/c/c99/n1256.html#6.7.8p19 The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject;132) all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration. In C11 the clause that was numbered 6.7.8:10 in C99 becomes 6.7.9:10 and the text is changed as follows: If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then: if it has pointer type, it is initialized to a null pointer; if it has arithmetic type, it is initialized to (positive or unsigned) zero; if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits; if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits; Now, I agree that it's possible to read the change in a way that only forces the initialization of partially initialized structs. But can this have been the intention of the standardization committee when they went to the trouble of making an explicit change to C11? The concern was likely to address some security issues with information leaks. If structs with initializers for every members do not have their padding initialized, then security issues with information leaks remain for structs with initializers for every members. Why would the committee have fixed only half of the problem?