Open actually-a-cat opened 10 months ago
/confirm
Following the above instructions caused a crash for me too.
VERSION: eaa25f5 TYPE: Signal MESSAGE: SIGSEGV: Segmentation fault STACK TRACE:
./cataclysm-tiles(debug_write_backtrace(std::ostream&)+0x40) [0x5651df059cd1]
./cataclysm-tiles(+0xbfd32e) [0x5651df03032e]
./cataclysm-tiles(+0xbfd64e) [0x5651df03064e]
/lib64/libc.so.6(+0x3dba0) [0x7f688bb50ba0]
./cataclysm-tiles(item_pocket::is_type(pocket_type) const+0x4) [0x5651df38be72]
./cataclysm-tiles(item_contents::can_contain_liquid(bool) const+0x28) [0x5651df32b282]
./cataclysm-tiles(reload_activity_actor::finish(player_activity&, Character&)+0x4ca) [0x5651ded4ebbc]
./cataclysm-tiles(player_activity::do_turn(Character&)+0xa70) [0x5651df8b6c90]
./cataclysm-tiles(do_turn()+0x48c) [0x5651df0c58d7]
./cataclysm-tiles(main+0x1f7d) [0x5651debaf179]
/lib64/libc.so.6(+0x27b4a) [0x7f688bb3ab4a]
/lib64/libc.so.6(__libc_start_main+0x8b) [0x7f688bb3ac0b]
./cataclysm-tiles(_start+0x2e) [0x5651ded04b9e]
Attempting to repeat stack trace using debug symbols…
debug_write_backtrace(std::ostream&)
…/src/debug.cpp:1227
std::__cxx11::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >::str() const
/usr/include/c++/9/sstream:678
log_crash
…/src/crash.cpp:86
signal_handler
…/src/crash.cpp:143
??
??:0
item_pocket::is_type(pocket_type) const
…/src/item_pocket.cpp:2258
item_contents::can_contain_liquid(bool) const
…/src/item_contents.cpp:1113 (discriminator 2)
reload_activity_actor::finish(player_activity&, Character&)
…/src/activity_actor.cpp:4542
player_activity::do_turn(Character&)
…/src/player_activity.cpp:383
do_turn()
…/src/do_turn.cpp:487
main
…/src/main.cpp:798
??
??:0
??
??:0
_start
??:?
This appears to be a use-after-free.
=================================================================
==82900==ERROR: AddressSanitizer: heap-use-after-free on address 0x6170071f1b10 at pc 0x000001dd19c9 bp 0x7ffe284b1d70 sp 0x7ffe284b1d68
READ of size 8 at 0x6170071f1b10 thread T0
#0 0x1dd19c8 in reload_activity_actor::finish(player_activity&, Character&) src/activity_actor.cpp:4531
#1 0x6e33246 in player_activity::do_turn(Character&) src/player_activity.cpp:383
#2 0x3792e18 in do_turn() src/do_turn.cpp:487
#3 0x50f2246 in main src/main.cpp:798
#4 0x7f676bbc0b89 in __libc_start_call_main (/lib64/libc.so.6+0x27b89) (BuildId: f888be5f5e7d58e04cabb8c675c7ab94e77dd68c)
#5 0x7f676bbc0c4a in __libc_start_main_alias_2 (/lib64/libc.so.6+0x27c4a) (BuildId: f888be5f5e7d58e04cabb8c675c7ab94e77dd68c)
#6 0x1bec874 in _start (/home/cdda/git/Cataclysm-DDA/cataclysm-tiles+0x1bec874) (BuildId: e4aef1b01396edfcad6032b16ed98a6cef71b03b)
0x6170071f1b10 is located 16 bytes inside of 736-byte region [0x6170071f1b00,0x6170071f1de0)
freed by thread T0 here:
#0 0x7f676ca34d28 in operator delete(void*, unsigned long) (/lib64/libasan.so.8+0xdad28) (BuildId: 542ad02088f38edfdba9d4bfa465b2299f512d3e)
#1 0x1e58608 in std::__new_allocator<std::_List_node<item> >::deallocate(std::_List_node<item>*, unsigned long) /usr/include/c++/13/bits/new_allocator.h:168
#2 0x1e5876c in std::allocator_traits<std::allocator<std::_List_node<item> > >::deallocate(std::allocator<std::_List_node<item> >&, std::_List_node<item>*, unsigned long) /usr/include/c++/13/bits/alloc_traits.h:516
#3 0x1e5876c in std::__cxx11::_List_base<item, std::allocator<item> >::_M_put_node(std::_List_node<item>*) /usr/include/c++/13/bits/stl_list.h:522
#4 0x1e5876c in std::__cxx11::_List_base<item, std::allocator<item> >::_M_clear() /usr/include/c++/13/bits/list.tcc:81
#5 0x46a11ed in std::__cxx11::_List_base<item, std::allocator<item> >::~_List_base() /usr/include/c++/13/bits/stl_list.h:575
#6 0x46a11ed in std::__cxx11::list<item, std::allocator<item> >::~list() /usr/include/c++/13/bits/stl_list.h:903
#7 0x46a11ed in item_pocket::~item_pocket() src/item_pocket.h:36
#8 0x46a12f3 in void std::__new_allocator<std::_List_node<item_pocket> >::destroy<item_pocket>(item_pocket*) /usr/include/c++/13/bits/new_allocator.h:194
#9 0x46a12f3 in void std::allocator_traits<std::allocator<std::_List_node<item_pocket> > >::destroy<item_pocket>(std::allocator<std::_List_node<item_pocket> >&, item_pocket*) /usr/include/c++/13/bits/alloc_traits.h:557
#10 0x46a12f3 in std::__cxx11::_List_base<item_pocket, std::allocator<item_pocket> >::_M_clear() /usr/include/c++/13/bits/list.tcc:77
#11 0x46a1395 in std::__cxx11::list<item_pocket, std::allocator<item_pocket> >::clear() /usr/include/c++/13/bits/stl_list.h:1594
#12 0x46a1395 in std::__cxx11::list<item_pocket, std::allocator<item_pocket> >::_M_move_assign(std::__cxx11::list<item_pocket, std::allocator<item_pocket> >&&, std::integral_constant<bool, true>) /usr/include/c++/13/bits/stl_list.h:2043
#13 0x46a14ad in std::__cxx11::list<item_pocket, std::allocator<item_pocket> >::operator=(std::__cxx11::list<item_pocket, std::allocator<item_pocket> >&&) /usr/include/c++/13/bits/stl_list.h:935
#14 0x46a14ad in item_contents::operator=(item_contents&&) src/item_contents.h:30
#15 0x450ee34 in item::operator=(item&&) src/item.cpp:593
#16 0x29e6f39 in Character::remove_weapon() src/character.cpp:3063
#17 0x817f31a in Character::remove_items_with[abi:cxx11](std::function<bool (item const&)> const&, int) src/visitable.cpp:672
#18 0x816d567 in visitable::remove_item(item&) src/visitable.cpp:547
#19 0x4a59d65 in item_location::impl::item_on_person::remove_item() src/item_location.cpp:430
#20 0x4a3706d in item_location::remove_item() src/item_location.cpp:1046
#21 0x2c61519 in operator() src/character_inventory.cpp:721
#22 0x2c617f9 in __invoke_impl<bool, Character::dispose_item(item_location&&, const std::string&)::<lambda()>&> /usr/include/c++/13/bits/invoke.h:61
#23 0x2c617f9 in __invoke_r<bool, Character::dispose_item(item_location&&, const std::string&)::<lambda()>&> /usr/include/c++/13/bits/invoke.h:114
#24 0x2c617f9 in _M_invoke /usr/include/c++/13/bits/std_function.h:290
#25 0x2c74815 in std::function<bool ()>::operator()() const /usr/include/c++/13/bits/std_function.h:591
#26 0x2c5f582 in Character::dispose_item(item_location&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) src/character_inventory.cpp:762
#27 0x28ffa0f in Character::unwield() src/character.cpp:7861
#28 0x2361eff in avatar::wield(item&, int) src/avatar.cpp:1400
#29 0x2363534 in avatar::wield(item&) src/avatar.cpp:1377
#30 0x2c6d77a in Character::i_add(item, bool, item const*, item const*, bool, bool, bool) src/character_inventory.cpp:298
#31 0x45f5a93 in item::reload(Character&, item_location, int) src/item.cpp:11679
#32 0x1dd175d in reload_activity_actor::finish(player_activity&, Character&) src/activity_actor.cpp:4522
#33 0x6e33246 in player_activity::do_turn(Character&) src/player_activity.cpp:383
#34 0x3792e18 in do_turn() src/do_turn.cpp:487
#35 0x50f2246 in main src/main.cpp:798
#36 0x7f676bbc0b89 in __libc_start_call_main (/lib64/libc.so.6+0x27b89) (BuildId: f888be5f5e7d58e04cabb8c675c7ab94e77dd68c)
#37 0x7f676bbc0c4a in __libc_start_main_alias_2 (/lib64/libc.so.6+0x27c4a) (BuildId: f888be5f5e7d58e04cabb8c675c7ab94e77dd68c)
#38 0x1bec874 in _start (/home/cdda/git/Cataclysm-DDA/cataclysm-tiles+0x1bec874) (BuildId: e4aef1b01396edfcad6032b16ed98a6cef71b03b)
previously allocated by thread T0 here:
#0 0x7f676ca33e28 in operator new(unsigned long) (/lib64/libasan.so.8+0xd9e28) (BuildId: 542ad02088f38edfdba9d4bfa465b2299f512d3e)
#1 0x1e91f91 in std::__new_allocator<std::_List_node<item> >::allocate(unsigned long, void const*) /usr/include/c++/13/bits/new_allocator.h:147
#2 0x1e92068 in std::allocator_traits<std::allocator<std::_List_node<item> > >::allocate(std::allocator<std::_List_node<item> >&, unsigned long) /usr/include/c++/13/bits/alloc_traits.h:482
#3 0x1e92068 in std::__cxx11::_List_base<item, std::allocator<item> >::_M_get_node() /usr/include/c++/13/bits/stl_list.h:518
#4 0x1e92068 in std::_List_node<item>* std::__cxx11::list<item, std::allocator<item> >::_M_create_node<item const&>(item const&) /usr/include/c++/13/bits/stl_list.h:710
#5 0x1e92241 in void std::__cxx11::list<item, std::allocator<item> >::_M_insert<item const&>(std::_List_iterator<item>, item const&) /usr/include/c++/13/bits/stl_list.h:2005
#6 0x1e927ac in std::__cxx11::list<item, std::allocator<item> >::push_back(item const&) /usr/include/c++/13/bits/stl_list.h:1306
#7 0x4a8e84e in item_pocket::insert_item(item const&, bool, bool, bool) src/item_pocket.cpp:2211
#8 0x47c278c in item_contents::combine(item_contents const&, bool, bool, bool, bool) src/item_contents.cpp:713
#9 0x7469da4 in item::deserialize(JsonObject const&) src/savegame_json.cpp:3241
#10 0x1ecefd6 in decltype ((({parm#1}.deserialize)(*this)),(true)) JsonValue::read<item>(item&, bool) const src/flexbuffer_json-inl.h:319
#11 0x1ecf2c5 in bool JsonObject::read<item>(std::basic_string_view<char, std::char_traits<char> >, item&, bool) const src/flexbuffer_json-inl.h:1065
#12 0x747a128 in Character::load(JsonObject const&) src/savegame_json.cpp:997
#13 0x74882c8 in avatar::load(JsonObject const&) src/savegame_json.cpp:1613
#14 0x748ca88 in avatar::deserialize(JsonObject const&) src/savegame_json.cpp:1608
#15 0x7403b48 in decltype ((({parm#1}.deserialize)(*this)),(true)) JsonValue::read<avatar>(avatar&, bool) const src/flexbuffer_json-inl.h:319
#16 0x7403e39 in bool JsonObject::read<avatar>(std::basic_string_view<char, std::char_traits<char> >, avatar&, bool) const src/flexbuffer_json-inl.h:1065
#17 0x73a9a1d in game::unserialize(std::istream&, cata_path const&) src/savegame.cpp:269
#18 0x3c924d8 in operator() src/game.cpp:3071
#19 0x3c92538 in __invoke_impl<void, game::load(const save_t&)::<lambda()>::<lambda(std::istream&)>&, std::basic_istream<char, std::char_traits<char> >&> /usr/include/c++/13/bits/invoke.h:61
#20 0x3c92538 in __invoke_r<void, game::load(const save_t&)::<lambda()>::<lambda(std::istream&)>&, std::basic_istream<char, std::char_traits<char> >&> /usr/include/c++/13/bits/invoke.h:111
#21 0x3c92538 in _M_invoke /usr/include/c++/13/bits/std_function.h:290
#22 0x2868d7d in std::function<void (std::istream&)>::operator()(std::istream&) const /usr/include/c++/13/bits/std_function.h:591
#23 0x2864b74 in read_from_file(std::filesystem::__cxx11::path const&, std::function<void (std::istream&)> const&) src/cata_utility.cpp:451
#24 0x2864fde in read_from_file(cata_path const&, std::function<void (std::istream&)> const&) src/cata_utility.cpp:441
#25 0x3e468be in operator() src/game.cpp:3068
#26 0x3e46b3a in __invoke_impl<void, game::load(const save_t&)::<lambda()>&> /usr/include/c++/13/bits/invoke.h:61
#27 0x3e46b3a in __invoke_r<void, game::load(const save_t&)::<lambda()>&> /usr/include/c++/13/bits/invoke.h:111
#28 0x3e46b3a in _M_invoke /usr/include/c++/13/bits/std_function.h:290
#29 0x1c06737 in std::function<void ()>::operator()() const /usr/include/c++/13/bits/std_function.h:591
#30 0x3d3af8b in game::load(save_t const&) src/game.cpp:3198
#31 0x5107921 in main_menu::load_game(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, save_t const&) src/main_menu.cpp:1030
#32 0x5114322 in main_menu::load_character_tab(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) src/main_menu.cpp:1100
#33 0x5127b26 in main_menu::opening_screen() src/main_menu.cpp:854
#34 0x50f1f22 in main src/main.cpp:792
#35 0x7f676bbc0b89 in __libc_start_call_main (/lib64/libc.so.6+0x27b89) (BuildId: f888be5f5e7d58e04cabb8c675c7ab94e77dd68c)
SUMMARY: AddressSanitizer: heap-use-after-free src/activity_actor.cpp:4531 in reload_activity_actor::finish(player_activity&, Character&)
Shadow bytes around the buggy address:
0x6170071f1880: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1900: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1980: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1a00: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
0x6170071f1a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x6170071f1b00: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1b80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1c00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1c80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1d00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x6170071f1d80: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==82900==ABORTING
I think item_location target_loc looses the item it was referring to and becomes a dangling pointer.
I think the bug is in item::reload - it checks that we are not wielding the item we are reloading, but does not check whether we are wielding a container that contains the item.
~Even in this case we are not supposed to crash - I will have to look into why safe_reference does not prevent a crash here~
Now I understand why safe_reference does not prevent a crash:
I'll make a patch for this by fixing item::reload as described in the previous comment
Describe the bug
crashy crashy
Attach save file
Landover-trimmed.tar.gz
Steps to reproduce
Expected behavior
no crashy
Screenshots
No response
Versions and configuration
Additional context
This is on a custom build with some patches but I tested that it reproduces on a stock build.