https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86913
Bug ID: 86913 Summary: Sending a nil message using a method signature returning a struct corrupts the stack Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: objc Assignee: unassigned at gcc dot gnu.org Reporter: yavor at gnu dot org Target Milestone: --- Created attachment 44524 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44524&action=edit Preprocessed source of the test program Josh Freeman discovered that sending a nil message using a method signature that returns a structure results in: 1. Garbage values in the returned structure's members (affects: x86/x86_64, with and without optimization) 2. A corrupted stack (affects: x86 with -O1 or -O2) After some investigation, I can confirm that this bug was fixed in April 2013 (r198140, PR target/57018). But the change was reverted in November 2013 as part of a fix for PR target/57293 (r205498). AFAICT all compiler versions are affected, except 4.8 (the fix was backported to the gcc-4_8-branch in May 2013). Minimized test program based on Josh's test program for GNUstep: ... #include <objc/runtime.h> #import <objc/Object.h> int printf (const char *, ...); struct Size { float w; float h; }; static const struct Size ZeroSize = {0.0, 0.0}; @interface NilMsgCheck : Object + (id) new; - (struct Size) nmcZeroSize; - (void) nmcSendNilMsg; @end @implementation NilMsgCheck + (id) new { return class_createInstance (self, 0); } - (struct Size) nmcZeroSize { return ZeroSize; } - (void) nmcSendNilMsg { struct Size size = [self nmcZeroSize]; printf ("[self nmcZeroSize] returned: w = %f; h = %f\n", size.w, size.h); size = [nil nmcZeroSize]; printf ("[nil nmcZeroSize] returned: w = %f; h = %f\n", size.w, size.h); } @end int main (void) { NilMsgCheck *object = [NilMsgCheck new]; [object nmcSendNilMsg]; return 0; } ... On x86_64-linux-gnu, it prints: [self nmcZeroSize] returned: w = 0.000000; h = 0.000000 [nil nmcZeroSize] returned: w = -nan; h = 0.000000 On x86-linux-gnu (with optimization) it segfaults (or, if built with -fstack-protector-strong it aborts with "stack smashing detected"). $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/home/yavor/libexec/gcc/i686-pc-linux-gnu/8.2.0/lto-wrapper Target: i686-pc-linux-gnu Configured with: ./configure --prefix=/home/yavor --disable-nls --disable-multilib --enable-languages=c,objc Thread model: posix gcc version 8.2.0 (GCC)