27

Today I have read an article about GCC Undefined Behavior Sanitizer (ubsan). However, when I follow steps there (add -fsanitize=undefined to my code), the compiler (GCC 4.9.2 on Ubuntu 15.04) says that some references are not defined:

||=== Build: Debug in Project (compiler: GNU GCC Compiler) ===|
obj/Debug/App.o||In function `App::OnInit()':|
/home/ilya/Project/App.cpp|31|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Project/App.cpp|31|undefined reference to `__ubsan_handle_load_invalid_value'|
...
obj/Debug/App.o||In function `wxObjectEventFunctor::operator()(wxEvtHandler*, wxEvent&)':|
/usr/include/wx-3.0/wx/event.h|3757|undefined reference to `__ubsan_handle_add_overflow'|
obj/Debug/App.o||In function `std::_Vector_base<unsigned long long, std::allocator<unsigned long long> >::~_Vector_base()':|
/usr/include/c++/4.9/bits/stl_vector.h|161|undefined reference to `__ubsan_handle_sub_overflow'|
...
||More errors follow but not being shown.|
||Edit the max errors limit in compiler options...|
||=== Build failed: 50 error(s), 0 warning(s) (0 minute(s), 23 second(s)) ===|

How can I fix this?

Ilya
  • 728
  • 2
  • 8
  • 22
  • 1
    Give this a try. From a comment on the page you linked to: "Note, libubsan may not be installed on your system by default. On fedora 21+ install as follows: `yum install libubsan`" – Michael Burr Aug 04 '15 at 08:08
  • I have installed `libubsan0` and `lib64ubsan0`, but nothing changed. Maybe I should link it somehow? – Ilya Aug 04 '15 at 08:31
  • 5
    Yes, I've added a -lubsan option, and it worked! (^_^) – Ilya Aug 04 '15 at 08:34

2 Answers2

23

The article you cited, as seen at its new home, already provides the answer, but you didn't notice it :-) With bold mine:

GCC recently (version 4.9) gained Undefined Behavior Sanitizer (ubsan), a run-time checker for the C and C++ languages. In order to check your program with ubsan, compile and link the program with -fsanitize=undefined option.

I think the correct way to solve this is not to manually link with ubsan, but instead to simply also pass -fsanitize=undefined to the linker, not just the compiler. Sure, reinventing the wheel might work for you, but it's not needed, and there might be a reason that there is a specific linker flag for this, instead.

Certainly, that works: I was suddenly getting piles of undefined reference errors and, after giving up and just not using it for months, yugr's answer here pointed me in the right direction: I was only passing -fsanitize=undefined to meson.add_project_arguments(), but those only go to the compiler; I also needed to pass it to meson.add_project_link_arguments(). After adding that, the errors are gone, and the program links.

underscore_d
  • 6,309
  • 3
  • 38
  • 64
  • It's been a general rule for ages that *all* compilation flags should be passed in the link phase and the compiler/linker driver will ignore any that are not needed, so if meson does not just pass everything from project arguments to project link arguments, I'd tend to call it a bug. – Jan Hudec Jun 07 '21 at 08:59
  • @JanHudec You might want to search Meson's issue tracker for such a bug then, or file it if there isn't one ;-) What I said is straight out of [Meson's reference manual](https://mesonbuild.com/Reference-manual.html). Specifically, `add_project_arguments()` is documented in terms of `add_global_arguments()`, which "_Adds the positional arguments to the compiler command line._" - whereas `add_global_link_arguments()` and `add_project_link_arguments()` are documented as "_Like `add_global|project_arguments` but the arguments are passed to the linker._" - and tbh I have no opinion on it either way – underscore_d Jun 07 '21 at 16:05
16

I have installed libubsan0 and lib64ubsan0 and added -lubsan option, and my application compiled successfully!

Ilya
  • 728
  • 2
  • 8
  • 22
  • I tried to add add_definitions("-fsanitize=undefined -lubsan") to my cmake, but still get the undefined reference error, even after installing the above two mentioned libraries, any ideas? – Hakaishin Aug 08 '19 at 13:59
  • How did you install? – Aykhan Hagverdili Sep 03 '19 at 14:53
  • 7
    UBsan developers have always suggested (e.g. [here](https://groups.google.com/forum/#!msg/address-sanitizer/SD590XDinfQ/NMUPj_G0BgAJ)) to avoid explicit `-lubsan`/`-lasan`/etc. and simply use `-fsanitize=undefined` both when compiling and linking code. One reason is that in case of clang UBSan runtime library consists of several different libraries with different names (not `libubsan.so`). Thus the underscore_d's answer is the correct one. – yugr Dec 20 '19 at 20:21
  • @yugr what should I do if my compile and link steps are separate? how can I pass "-fsanitize=undefined" to ld? I would have to just pass "-lubsan_lib.so" right? where ubsan_lib.so is a file I would download and put somewhere that ld can find it? – Elliot Gorokhovsky Oct 20 '21 at 22:17
  • 1
    @ElliotGorokhovsky in general you should avoid explicit usage of `ld` (as it's not portable) and use gcc/clang driver for linking instead. To link with Asan/UBsan just add `-fsanitize=...` to `LDFLAGS`. – yugr Oct 21 '21 at 10:15
  • @yugr Thanks. Unfortunately I am trying to get this to work in a large project where the link step is separate from the compile step: https://zephyrproject.org/. Hopefully the LDFLAGS method will work. – Elliot Gorokhovsky Oct 21 '21 at 14:28
  • 1
    @ElliotGorokhovsky that's interesting. In that case I suggest to run `gcc -v -fsanitize=...` on a dummy file and see what flags `ld` is run with. On my system it's `libasan_preinit.o --push-state --no-as-needed -lasan --pop-state` (I told you, it's ugly). – yugr Oct 21 '21 at 15:23
  • thanks, I'll try that and let you know what happens! – Elliot Gorokhovsky Oct 21 '21 at 18:37