From 6dc7f63ac55938068f72d8bbaa7add7295f2ecc1 Mon Sep 17 00:00:00 2001 From: inogenous <123803852+inogenous@users.noreply.github.com> Date: Sun, 4 Aug 2024 17:21:51 +0200 Subject: [PATCH] Prevent segfault if repair item disappears (#75413) 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 );