In the following case (https://godbolt.org/z/cXxBXz): #include <stdio.h> int main(int argc, char **argv) { switch (argc) { int v; case 1: v = 2; default: printf("v(%p): %x\n", &v, v); } return 0; } Clang doesn't force-initialize |v| when run with -ftrivial-auto-var-init=pattern: $ ./t 2 v(0x7ffcab198224): 7ffc In the case |v| is moved outside the switch (https://godbolt.org/z/CKPQNz) Clang emits the initialization correctly: $ ./t 2 v(0x7ffee8020c44): aaaaaaaa
FWIW this was a known limitation from the RFC: https://reviews.llvm.org/D54604 IIURC this is a decent amount of work to fix, and I think we'd be better off diagnosing and fixing this type of code.
> FWIW this was a known limitation from the RFC: https://reviews.llvm.org/D54604 > IIURC this is a decent amount of work to fix, and I think we'd be better off > diagnosing and fixing this type of code. Assignments performed in switch statements are indeed unreachable, and a local variable declared in a switch remains uninitialized. But aren't we trying to guarantee that uninitialized locals are now initialized? Asking the users to proactively fix their code kind of contradicts with the goal of giving them the flag :) Also, Linux kernel community will probably oppose to attempts to fix the code in which a local is declared inside a switch statement, but is always initialized before every first use.
Note that GCC will actually warn about finding surprise initializers in these cases. Can Clang add that more easily than fixing the situation? (This would get us into the state of "least surprise", in the sense that the condition will warn instead of silently missing initialization.) fs/fcntl.c: In function ‘send_sigio_to_task’: fs/fcntl.c:738:13: warning: statement will never be executed [-Wswitch-unreachab le] siginfo_t si; ^~
(In reply to Kees Cook from comment #3) > Note that GCC will actually warn about finding surprise initializers in > these cases. Can Clang add that more easily than fixing the situation? (This > would get us into the state of "least surprise", in the sense that the > condition will warn instead of silently missing initialization.) > > fs/fcntl.c: In function ‘send_sigio_to_task’: > fs/fcntl.c:738:13: warning: statement will never be executed > [-Wswitch-unreachab > le] > siginfo_t si; > ^~ That's the route I would take, but if someone is interested in implementing the completely correct fix (where skipped-over initializations still execute for auto-init) then I'm all for it.
Updated godbolt to show uninit, pattern, and zero cases: https://godbolt.org/z/9Kecrd
> Assignments performed in switch statements are indeed unreachable, and a > local variable declared in a switch remains uninitialized. > But aren't we trying to guarantee that uninitialized locals are now > initialized? Asking the users to proactively fix their code kind of > contradicts with the goal of giving them the flag :) Isn't the feature a mitigation to reduce probability of exploits on these kind of bugs and not language feature which guaranty initialization? Users are still have to fix them.
-ftrivial-auto-var-init=pattern|zero should be deterministic for all automatic variables. Currently it is not (this case), but it also doesn't even warn about it. It's totally silent. So a minimum solution should at least warn about the condition, if it doesn't fix it.
(In reply to Kees Cook from comment #7) > -ftrivial-auto-var-init=pattern|zero should be deterministic for all > automatic variables. Currently it is not (this case), but it also doesn't > even warn about it. It's totally silent. So a minimum solution should at > least warn about the condition, if it doesn't fix it. Either will be improvement, just saying that "guaranty" is too strong. Probably JumpScopeChecker can be more strict with -ftrivial-auto-var-init.