Created attachment 2130 [details] test.c Git rev: master/429802fe6691c8a70ec9735c0db4c6a4e1e1b038 The attachment is a piece of C code. When compile it with -O2 option, a segfault occurs: ################## root@qemux86-64:~# gcc -o test test.c root@qemux86-64:~# ./test 192.168.1.1 root@qemux86-64:~# root@qemux86-64:~# gcc -O2 -o test test.c root@qemux86-64:~# ./test test[893]: segfault at 0 ip 0000000000400944 sp 00007fff87c8f0f0 error 4 in test[400000+1000] Segmentation fault root@qemux86-64:~# ################## gcc version 4.9.1 (GCC) This issue happens on all qemus and BSPs, regardless the archs. I test it on Yocto 1.6.1, it works well: ################### root@qemux86-64:~# gcc -o test test.c root@qemux86-64:~# ./test 192.168.1.1 root@qemux86-64:~# gcc -O2 -o test test.c root@qemux86-64:~# ./test 192.168.1.1 root@qemux86-64:~# ################### gcc version 4.8.2 (GCC) I also test it on some linux distributions, it works well on all of them: Ubuntu 12.04 x86_64: gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) Ubuntu 14.04 x86_64: gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) Fedora 20 x86 and x86_64: gcc version 4.8.3 20140624 (Red Hat 4.8.3-1) (GCC)
The native compiler produces the same assembly code hence the same error when optimized for any level other than "1", it seems like it is a gcc-4.9 issue.
does this same binary when run on pc segfault too?
Yes the compiled binary segfaults on both the host and target as far as I understand from Alejandro, I will confirm.
Hmm although it crashes but it does not seem like a compiler issue. You might have a coding error in your application. Whats happening is that at -O2 gcc is reordering NULL pointer checks in a way that dereferencing is happening before NULL pointer check. strncpy(new, old, cp-old); here if old is NULL then its undefined behavior which is what you are seeing. and gcc assumes that old can never be NULL.
This is how you can fix it in your code --- a.c 2014-10-04 12:28:46.918718452 -0700 +++ a.c.khem 2014-10-04 13:54:41.905347173 -0700 @@ -36,9 +36,11 @@ else cp = cp + strlen(cp); } - - strncpy(new, old, cp-old); - new[cp-old] = 0; + if (old) { + strncpy(new, old, cp-old); + new[cp-old] = 0; + } else + new[0] = 0; if (cp != old && !*cp) strcat(new, ",");
If the results are different since use different Gcc parameter to building, it should be Gcc bug. Gcc should keep the same behaviours among different versions, but 4.6.3 and 4.8.2 can work, 4.9.1 did not work...
(In reply to comment #6) > If the results are different since use different Gcc parameter to building, > it should be Gcc bug. > > Gcc should keep the same behaviours among different versions, but 4.6.3 and > 4.8.2 can work, 4.9.1 did not work... No. A C compiler complies to C standard and where behavior is undefined like this case it has liberty to do whatever it wishes. If your code has been relying on undefined behavior go fix the code, not the compiler.
which line is undefined? strncpy(new, 0, 0)? no, it should work since the length of strncpy is 0, and src of strncpy will not be used. I think any change can make these codes work, since any change will make the gcc optimize to change
(In reply to comment #8) > which line is undefined? strncpy(new, 0, 0)? no, it should work since the > length of strncpy is 0, and src of strncpy will not be used. I could not infer this from OpenGroup standardIEEE Std 1003.1 where strncpy is defined. can you kindly show me which standard describes strncpy behavior the way you are mentioning ? > > I think any change can make these codes work, since any change will make the > gcc optimize to change Not anything, you have to describe your expected behavior by guarding it with source being valid.
From the test result, strncpy(buf, 0,0) works. -------------------------------------- #cat aa.c #include <string.h> main() { char buf[10]; strncpy(buf, 0, 0); } # #./sysroots/x86_64-linux/usr/libexec/x86_64-wrs-linux/gcc/x86_64-wrs-linux/4.9.0/x86_64-wrs-linux-gcc -O2 aa.c # #./a.out # ----------------------------------- but ./sysroots/x86_64-linux/usr/libexec/x86_64-wrs-linux/gcc/x86_64-wrs-linux/4.9.0/x86_64-wrs-linux-gcc -O2 /tmp/test.c # #./a.out Segmentation fault (core dumped) #
man strncpy, it says: A simple implementation of strncpy() might be: char * strncpy(char *dest, const char *src, size_t n) { size_t i; for (i = 0; i < n && src[i] != '\0'; i++) dest[i] = src[i]; for ( ; i < n; i++) dest[i] = '\0'; return dest; }
and you think man strcpy is what standards depend upon ? Please compare the assembly code it will generate for the example you are sighting. Its passing a direct NULL pointer, gcc is smart enough to know that its no way representative of the original testcase. I have explained it enough and I do not have more time for it. I am assigning this bug to you and if you feel like fixing it in gcc feel free to. if not you are also welcome to raise this with gcc community.
OK, I will paste it to GCC community
https://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg433516.html
GCC community think this is a testcase bug, same as Khem Raj. and Khem Raj's patch works. Thanks
This looks like NOTABUG. Setting accordingly.