Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running wesnoth after building with UBSan results in invalid vptr errors #2400

Closed
Pentarctagon opened this issue Jan 26, 2018 · 12 comments
Closed
Labels
Bug Issues involving unexpected behavior. Confirmed Issues that have been successfully reproduced by at least one developer. Linux OS-specific issues that apply to Linux-based operating systems.

Comments

@Pentarctagon
Copy link
Member

Pentarctagon commented Jan 26, 2018

When building current master with Undefined Behavior Sanitizer enabled in GCC:
scons wesnoth multilib_arch=64 build=debug enable_lto=no nls=no ctool=gcc cxxtool=g++ jobs=6 --option-cache="" sanitize=undefined

Launching wesnoth-debug results in it exiting with the following error before the main menu appears:

src/gui/widgets/window.cpp:276:108: runtime error: member call on address 0x00000a9bfc60 which does not point to an object of type 'window'
0x00000a9bfc60: note: object has invalid vptr
 00 00 00 00  78 7b 3b 68 85 7f 00 00  10 5d 9c 0a 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
fish: “./wesnoth-debug” terminated by signal SIGSEGV (Address boundary error)

Using GCC 5.4.0 on Mint 18.3.

@GregoryLundberg GregoryLundberg added Bug Issues involving unexpected behavior. Confirmed Issues that have been successfully reproduced by at least one developer. Linux OS-specific issues that apply to Linux-based operating systems. labels Jan 26, 2018
@GregoryLundberg
Copy link
Contributor

I rebuilt using the command shown and I cannot reproduce this crash. The game loads and I can play AToTB just fine.

However, when I check the console log I see:

[lundberg@lundberg-arch wesnoth]$ ./wesnoth-debug 
Battle for Wesnoth v1.13.10+dev (763c323768-Clean)
Started on Fri Jan 26 13:53:03 2018

Automatically found a possible data directory at /home/lundberg/wesnoth

Data directory:               /home/lundberg/wesnoth
User configuration directory: /home/lundberg/.config/wesnoth
User data directory:          /home/lundberg/.local/share/wesnoth/1.13
Cache directory:              /home/lundberg/.cache/wesnoth

Setting mode to 1360x713
src/gui/widgets/window.cpp:276:108: runtime error: member call on address 0x55e30370c500 which does not point to an object of type 'window'
0x55e30370c500: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  00 cf 70 03 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/spacer.cpp:32:44: runtime error: member call on address 0x55e303980fb0 which does not point to an object of type 'spacer'
0x55e303980fb0: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  b0 28 68 03 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/image.cpp:40:44: runtime error: member call on address 0x55e303513d50 which does not point to an object of type 'image'
0x55e303513d50: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  0a 09 09 64 65 66 69 6e  00 00 00 00 00 00 00 00  22 62 6f 78
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/label.cpp:44:44: runtime error: member call on address 0x55e303a0b100 which does not point to an object of type 'label'
0x55e303a0b100: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  a0 fe 8b 03 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
Checking lua scripts... ok
src/gui/widgets/stacked_widget.cpp:60:45: runtime error: member call on address 0x55e303843c00 which does not point to an object of type 'stacked_widget'
0x55e303843c00: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  c0 e8 b2 03 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/panel.cpp:39:68: runtime error: member call on address 0x55e3036055d0 which does not point to an object of type 'panel'
0x55e3036055d0: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  e0 c9 79 03 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/multi_page.cpp:37:45: runtime error: member call on address 0x55e303863920 which does not point to an object of type 'multi_page'
0x55e303863920: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  50 31 c0 03 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/button.cpp:44:44: runtime error: member call on address 0x55e3035fc610 which does not point to an object of type 'button'
0x55e3035fc610: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  13 00 00 00 e3 55 00 00  00 00 00 00 00 00 00 00  44 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/scrollbar_panel.cpp:36:50: runtime error: member call on address 0x55e303784520 which does not point to an object of type 'scrollbar_panel'
0x55e303784520: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  20 f2 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  10 45 78 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/vertical_scrollbar.cpp:32:45: runtime error: member call on address 0x55e303787060 which does not point to an object of type 'vertical_scrollbar'
0x55e303787060: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  f0 f1 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  50 70 78 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/horizontal_scrollbar.cpp:37:45: runtime error: member call on address 0x55e3036d0050 which does not point to an object of type 'horizontal_scrollbar'
0x55e3036d0050: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  30 f2 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  40 00 6d 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/toggle_button.cpp:40:44: runtime error: member call on address 0x55e3037b20f0 which does not point to an object of type 'toggle_button'
0x55e3037b20f0: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  40 f2 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  e0 20 7b 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/tree_view.cpp:41:50: runtime error: member call on address 0x55e30377f530 which does not point to an object of type 'tree_view'
0x55e30377f530: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  60 f1 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  20 f5 77 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/multimenu_button.cpp:43:44: runtime error: member call on address 0x55e3037e7830 which does not point to an object of type 'multimenu_button'
0x55e3037e7830: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  80 b7 f9 03 e3 55 00 00  00 00 00 00 00 00 00 00  80 b7 f9 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/toggle_panel.cpp:41:36: runtime error: member call on address 0x55e303805910 which does not point to an object of type 'toggle_panel'
0x55e303805910: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  d0 f1 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  00 59 80 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/scroll_label.cpp:43:50: runtime error: member call on address 0x55e303fa20f0 which does not point to an object of type 'scroll_label'
0x55e303fa20f0: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  d0 ef 82 54 75 7f 00 00  00 00 00 00 00 00 00 00  e0 20 fa 03
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/listbox.cpp:58:50: runtime error: member call on address 0x55e306284530 which does not point to an object of type 'listbox'
0x55e306284530: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  10 30 aa 06 e3 55 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
src/gui/widgets/text_box.cpp:99:44: runtime error: member call on address 0x55e307542000 which does not point to an object of type 'text_box'
0x55e307542000: note: object has invalid vptr
 00 00 00 00  00 00 00 00 00 00 00 00  b0 0e 85 07 e3 55 00 00  00 00 00 00 00 00 00 00  b0 0e 85 07
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
[lundberg@lundberg-arch wesnoth]$ 

@GregoryLundberg
Copy link
Contributor

My first reaction is someone is static_cast'ing from to a non-derived class.

A bit of research on SO and others a claiming it's a buffer overrun. But I think that's unlikely.
The answer not marked as accepted is that any undefined behavior can cause it. I find that more likely.

Another likely culprit I'm seeing mentioned is calling a pure virtual method from the constructor; which also seems likely.

@Pentarctagon
Copy link
Member Author

Pentarctagon commented Jan 26, 2018

It looks like the difference is that when I run it, it's set to exit on the first problem it hits, whereas for you it keeps going. The documentation for -fsanitize-recover says that this behavior is enabled by default, though that doesn't seem to be the case for me for whatever reason.

@GregoryLundberg
Copy link
Contributor

Well, considering it all has to do with GUI junk, perhaps @Vultraz needs to take a look.

@GregoryLundberg
Copy link
Contributor

The game is running, and not crashing, without this option. So I'd say it's static_cast<> or something like that and the missing base class with at least one virtual function isn't being called.

This should be fixed, but without a crash, it's not critical.

@Pentarctagon Pentarctagon changed the title Running wesnoth after building with UBSan results in crash when launching Running wesnoth after building with UBSan results in invalid vptr errors Jan 26, 2018
@jyrkive
Copy link
Member

jyrkive commented Jan 27, 2018

The problem is caused by calling a virtual function in an initializer list: https://stackoverflow.com/a/25755113

@CelticMinstrel
Copy link
Member

So it looks like this is actually a fundamental flaw in the design of GUI2: every widget must define get_control_type() which is a virtual method that returns, basically, the name of the class. Every class then passes that to the parent class in the constructor initializer list, thus triggering these errors.

I'm not sure what's the best way to fix this. The registration procedure would work just as well if the method were non-virtual, or even just a static member variable; however, that would break any call of get_control_type() through a pointer to the parent class.

@GregoryLundberg
Copy link
Contributor

Default construct the base in the init list and call a protected function in the init body. The problem is you cannot call the virtual from the base until the unit list is done so use the protected to do it when it is safe.

@CelticMinstrel
Copy link
Member

CelticMinstrel commented Jan 27, 2018

Looking more closely, I don't see why the function even needs to be virtual. It could just be non-virtual in styled_widget and return a private data member. The only problem then is that I'm not sure how the registration macro would expose it so that it can be passed to the constructor... a static data member would work, but requires a declaration in the header, while a file static doesn't require a prior declaration but might cause problems when two widgets are registered in the same file.

Currently the string isn't stored in the class at all and is only used by styled_widget as an argument to get_control (a free function).

@Pentarctagon
Copy link
Member Author

Rather belated, but for:

src/gui/widgets/window.cpp:275:108: runtime error: member call on address 0x000009107240 which does not point to an object of type 'window'
0x000009107240: note: object has invalid vptr
 00 00 00 00  78 8b 0d f3 ff 7f 00 00  20 7c 10 09 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr

I get a bracktrace of:

#0  0x00007ffff4395f93 in __dynamic_cast () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007ffff32fdf10 in ?? () from /usr/lib/x86_64-linux-gnu/libubsan.so.0
#2  0x00007ffff32fd396 in ?? () from /usr/lib/x86_64-linux-gnu/libubsan.so.0
#3  0x00007ffff32fdbd3 in __ubsan_handle_dynamic_type_cache_miss () from /usr/lib/x86_64-linux-gnu/libubsan.so.0
#4  0x000000000064b140 in gui2::spacer::spacer (this=0xaefa550, builder=..., w="", h="((screen_height - if(screen_height < 800, 200, 0)) / 3.5)") at src/gui/widgets/spacer.cpp:32
#5  0x000000000064c3b0 in gui2::implementation::builder_spacer::build (this=0xadafee0) at src/gui/widgets/spacer.cpp:182
#6  0x0000000000c4e6f5 in gui2::builder_grid::build (this=0xadb0d10, grid=0x9107638) at src/gui/core/window_builder.cpp:475
#7  0x0000000000d8b90c in gui2::container_base::init_grid (this=0x9107240, grid_builder=std::shared_ptr (count 1, weak 0) 0xadb0d10) at src/gui/widgets/container_base.cpp:272
#8  0x0000000000c464e8 in gui2::build (definition=0xadafc70) at src/gui/core/window_builder.cpp:75
#9  0x0000000000c4676c in gui2::build (type="loading_screen") at src/gui/core/window_builder.cpp:86
#10 0x0000000000cae661 in gui2::dialogs::modal_dialog::build_window (this=0x7fffffffd490) at src/gui/dialogs/modal_dialog.cpp:221
#11 0x0000000000cac8e7 in gui2::dialogs::modal_dialog::show (this=0x7fffffffd490, auto_close_time=0) at src/gui/dialogs/modal_dialog.cpp:76
#12 0x0000000000c88400 in gui2::dialogs::loading_screen::display(std::function<void ()>) (f=...) at src/gui/dialogs/loading_screen.cpp:223
#13 0x000000000075b5fa in do_gameloop (args=std::vector of length 1, capacity 1 = {...}) at src/wesnoth.cpp:725
#14 0x000000000075dcc9 in main (argc=1, argv=0x7fffffffe678) at src/wesnoth.cpp:1143

@Pentarctagon
Copy link
Member Author

It also seems somewhat likely that this is related to the segfault that the boost unit tests get when LTO is enabled:

Thread 1 (Thread 0x7ffff7fbf980 (LWP 6695)):
#0  0x0000555555a7974b in gui2::dialogs::loading_screen::display(std::function<void ()>) ()
#1  0x0000555555b341f4 in game_config_manager::load_game_config_with_loadscreen(game_config_manager::FORCE_RELOAD_CONFIG, game_classification const*) ()
#2  0x0000555555b3447f in game_config_manager::init_game_config(game_config_manager::FORCE_RELOAD_CONFIG) ()
#3  0x000055555587bdfd in boost::unit_test::ut_detail::global_configuration_impl<mp_connect_fixture>::test_start(unsigned long) ()
#4  0x00007ffff7b552ce in boost::detail::function::function_obj_invoker0<boost::detail::forward, int>::invoke(boost::detail::function::function_buffer&) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#5  0x00007ffff7b5477d in boost::execution_monitor::catch_signals(boost::function<int ()> const&) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#6  0x00007ffff7b54861 in boost::execution_monitor::execute(boost::function<int ()> const&) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#7  0x00007ffff7b54fdd in boost::execution_monitor::vexecute(boost::function<void ()> const&) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#8  0x00007ffff7b838d1 in boost::unit_test::unit_test_monitor_t::execute_and_translate(boost::function<void ()> const&, unsigned int) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#9  0x00007ffff7b586c1 in boost::unit_test::framework::run(unsigned long, bool) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#10 0x00007ffff7b8113f in boost::unit_test::unit_test_main(bool (*)(), int, char**) () at /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#11 0x0000555555936ceb in main ()

@Vultraz Vultraz closed this as completed in 52f7fcf Jun 8, 2018
@Pentarctagon
Copy link
Member Author

This also fixed the boost unit tests segafulting, FTR.

jostephd pushed a commit to jostephd/wesnoth that referenced this issue Oct 6, 2018
…et_control_type

Fixes wesnoth#2400. See comment in styled_widget.hpp for details.
jostephd pushed a commit to jostephd/wesnoth that referenced this issue Oct 7, 2018
…et_control_type

Fixes wesnoth#2400. See comment in styled_widget.hpp for details.

(cherry-picked from commit 52f7fcf)
gfgtdf pushed a commit to gfgtdf/wesnoth that referenced this issue Oct 7, 2018
…et_control_type

Fixes wesnoth#2400. See comment in styled_widget.hpp for details.
gfgtdf pushed a commit that referenced this issue Oct 7, 2018
…et_control_type

Fixes #2400. See comment in styled_widget.hpp for details.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Issues involving unexpected behavior. Confirmed Issues that have been successfully reproduced by at least one developer. Linux OS-specific issues that apply to Linux-based operating systems.
Projects
None yet
Development

No branches or pull requests

4 participants