From dd10542f96f2e58d3677bdf470b8d76f311d2f72 Mon Sep 17 00:00:00 2001 From: inogenous <123803852+inogenous@users.noreply.github.com> Date: Sat, 3 Aug 2024 09:39:03 +0200 Subject: [PATCH] Prevent segfault if repair item disappears Prevents segfault that could previously occur if the item being repaired was invalidated. The target item being repaired could get invalidated for various reasons, such as a follower moving it via zone sorting, the item could burn up in a fire, etc. Previous segfault that this commit attempts to prevent: ``` #0 0x0000555555ef9057 in item::is_null (this=this@entry=0x0) at src/item.cpp:943 #1 0x000055555602322c in repair_item_actor::can_repair_target (this=this@entry=0x555560003e80, pl=..., fix=..., print_msg=print_msg@entry=true, check_consumed_available=check_consumed_available@entry=true) at src/iuse_actor.cpp:2920 #2 0x00005555560243c2 in repair_item_actor::repair (this=this@entry=0x555560003e80, pl=..., tool=..., fix=..., refit_only=refit_only@entry=false) at src/iuse_actor.cpp:3106 #3 0x00005555559d5b55 in repair_item_finish (act=0x5555580cdf58, you=0x5555580cd890, no_menu=false) at src/activity_handlers.cpp:2477 #4 0x0000555555a00f52 in std::function::operator()(player_activity*, Character*) const (this=, __args#0=, __args#0@entry=0x5555580cdf58, __args#1=, __args#1@entry=0x5555580cd890) at /usr/include/c++/13/bits/std_function.h:591 #5 0x00005555559ff229 in activity_type::call_finish (this=, act=act@entry=0x5555580cdf58, you=you@entry=0x5555580cd890) at src/activity_type.cpp:168 #6 0x00005555564e368b in player_activity::do_turn (this=0x5555580cdf58, you=...) at src/player_activity.cpp:393 #7 0x0000555555cec856 in do_turn () at src/do_turn.cpp:532 #8 0x0000555555776e74 in main (argc=, argv=) at src/main.cpp:873 ``` Instead, this commit adds a message shown to the player if the target item is no longer valid for whatever reason. --- src/activity_handlers.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index c153a814b1abc..2ed5086514203 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -2471,6 +2471,12 @@ void repair_item_finish( player_activity *act, Character *you, bool no_menu ) // Valid Repeat choice and target, attempt repair. if( repeat != repeat_type::INIT && act->targets.size() >= 2 ) { item_location &fix_location = act->targets[1]; + if( !fix_location ) { + // The item could disappear for various reasons: moved by follower, burned up, eaten by a grue, etc. + you->add_msg_if_player( m_warning, _( "You can no longer find the item to repair." ) ); + act->set_to_null(); + return; + } // Remember our level: we want to stop retrying on level up const int old_level = you->get_skill_level( actor->used_skill );