[llvm-dev] broken C code only when optimized "-O2"

Adrian Moreno via llvm-dev llvm-dev at lists.llvm.org
Tue Dec 21 10:22:56 PST 2021


Thanks Sterling

On 12/21/21 18:31, Sterling Augustine wrote:
> The thing to do with problems like this is to run with clang's sanitizers, which 
> diagnose undefined behavior, memory errors, and other such issues that often 
> show up only under optimization. A cursory look at all the casting in this 
> example makes me think there is undefined behavior, but there very well could be 
> another type of failure.

Interestingly, when I enable UndefinedBehaviorSanitizer, my problem disappears 
(and sanitizer does not report anything). In fact, the issue is quite elisuve, 
adding a function call, a compiler barrier or not inlining a single function 
changes the behavior of the program.

MemorySanitizer does print an error that I'm investigating:

==762381==WARNING: MemorySanitizer: use-of-uninitialized-value
[Detaching after fork from child process 764910]
     #0 0x4b1871 in hmap_next__ 
/home/amorenoz/code/ovs/out/include/openvswitch/hmap.h:379:13
     #1 0x4af81f in hmap_first 
/home/amorenoz/code/ovs/out/include/openvswitch/hmap.h:391:12
     #2 0x4adf3a in main /home/amorenoz/dev/bugs/2014942/example.c:82:5
     #3 0x7ffff77c055f in __libc_start_call_main (/lib64/libc.so.6+0x2d55f)
     #4 0x7ffff77c060b in __libc_start_main at GLIBC_2.2.5 (/lib64/libc.so.6+0x2d60b)
     #5 0x42c244 in _start (/home/amorenoz/devel/bugs/2014942/example_+0x42c244)

   Uninitialized value was stored to memory at
     #0 0x4b17d8 in hmap_next__ 
/home/amorenoz/code/ovs/out/include/openvswitch/hmap.h:378:27
     #1 0x4af81f in hmap_first 
/home/amorenoz/code/ovs/out/include/openvswitch/hmap.h:391:12
     #2 0x4adf3a in main /home/amorenoz/dev/bugs/2014942/example.c:82:5
     #3 0x7ffff77c055f in __libc_start_call_main (/lib64/libc.so.6+0x2d55f)

   Uninitialized value was created by a heap allocation
     #0 0x45c942 in malloc (/home/amorenoz/devel/bugs/2014942/example_+0x45c942)
     #1 0x4b4c9d in xmalloc__ /home/amorenoz/code/ovs/lib/util.c:137:15
     #2 0x4b4c9d in xmalloc /home/amorenoz/code/ovs/lib/util.c:172:12

> 
> https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html 
> <https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html>
> https://clang.llvm.org/docs/AddressSanitizer.html 
> <https://clang.llvm.org/docs/AddressSanitizer.html>
> https://clang.llvm.org/docs/MemorySanitizer.html 
> <https://clang.llvm.org/docs/MemorySanitizer.html>
> 
> 
> On Tue, Dec 21, 2021 at 9:30 AM Adrian Moreno via llvm-dev 
> <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote:
> 
>     Hello,
> 
>     I need some help understanding what might be wrong with a piece of code from
>     the
>     openvswitch project. By ${subject} I'm not suggesting there's a problem in
>     clang, gcc also shows the same behavior so it's likely our code is broken. I am
>     kindly asking for help to understand/troubleshoot the problem.
> 
>     Summary: It seems that certain interaction between two main openvswitch data
>     structures, when optimized ("-O2 -flto=auto") is broken.
>     The two data structures are:
> 
>     hmap:
>     https://github.com/openvswitch/ovs/blob/master/include/openvswitch/hmap.h
>     <https://github.com/openvswitch/ovs/blob/master/include/openvswitch/hmap.h>
>     list:
>     https://github.com/openvswitch/ovs/blob/master/include/openvswitch/list.h
>     <https://github.com/openvswitch/ovs/blob/master/include/openvswitch/list.h>
> 
>     I've reproduced the problem outside of openvswitch daemon using a short C
>     program (attached)
> 
>     Code snippet:
> 
>     struct bond {
>           struct hmap members;
>     };
> 
>     struct member {
>           struct hmap_node hmap_node;
>           int order;
>           struct ovs_list elem;
>     };
> 
>     int main() {
>           int ret = 0;
>           struct member *member, *member1, *member2;
>           struct bond *bond;
>           struct ovs_list start = {0};
> 
>           bond = malloc(sizeof *bond);
>           memset(bond, 0, sizeof (struct bond));
>           hmap_init(&bond->members);
> 
>           member1 = malloc(sizeof *member1);
>           member2 = malloc(sizeof *member2);
>           memset(member1, 0, sizeof (struct member));
>           memset(member2, 0, sizeof (struct member));
> 
>           member1->order = 3;
>           member2->order = 2;
> 
>           hmap_insert(&bond->members, &member1->hmap_node,
>     (uint32_t)(uintptr_t)member1);
>           hmap_insert(&bond->members, &member2->hmap_node,
>     (uint32_t)(uintptr_t)member2);
> 
>           ovs_list_init(&start);
>           HMAP_FOR_EACH (member, hmap_node, &bond->members) {
>              /*
>               * Insert member in start (sorted)
>               * */
>              struct member *pos;
>              LIST_FOR_EACH (pos, elem, &start) {
>                  if (member->order > pos->order) {
>                      break;
>                  }
>              }
>              // TESTED: If I add this printf, the problem disappears
>              //printf("Inserting member: %p\n", member);
>              ovs_list_insert(&pos->elem, &member->elem);
>           }
> 
>           /* I've inserted two members into the 'start' list.
>            *   first and last have to be either member1 or member2
>            * */
>           if ((first != member1 && first != member2) || (last != member1 && last !=
>     member2)) {
>               printf("list is broken!\n");
>           }
> 
>     }
> 
> 
>     What I know for now:
>     * -fno-strict-aliasing does not fix it
>     * Only happens with "-O2 -flto=auto"
>     * If I define 'ovs_list *start' and change the code to use the pointer directly
>     and not '&start' the problem disappears. It seems that the LIST_FOR_EACH macros
>     prefer an lvalue rather than "&" but I don't get why.
>     * I'm not able to reproduce without using hmap _and_ ovs_list.
>     * If I add a compiler barrier (or a call to an external function) after the
>     loop, the problem disappears (e.g printf), the problem disappears.
>     * If I add -fsanitize=undefined the problem disappears!
> 
>     I'd really appreciate any hint or idea to try to understand this problem.
> 
>     Thanks in advanced.
> 
>     -- 
>     Adrián Moreno_______________________________________________
>     LLVM Developers mailing list
>     llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
>     https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>     <https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev>
> 

-- 
Adrián Moreno



More information about the llvm-dev mailing list