heap-use-after-free
I have tried a git clone as well as the 251 .tgz release. Both compile cleanly without warnings or errors. I am currently on Ubuntu 24.04.1 LTS I upgraded from Ubuntu 22 to 24 because it seems that 22 lacked support for the new changes to strlcpy, so I figured it was time. I was able to get an older version of AFKMud (2.2.3) that I've been using to work by including some C header files and modifying some vsnprintf statements, and seems to be working fine minus a couple warnings I need to fix.
My issue with the 2.5.1 though is beyond me - but I think it might be caused by from_room and mprog_greet looking for the old pointer? I can recreate this by using 'goto 2850' and moving south which I think causes a greet program with an mptrlook to trigger.
==30548==ERROR: AddressSanitizer: heap-use-after-free on address 0x5030003bf5d0 at pc 0x555555ad4340 bp 0x7fffffffaa50 sp 0x7fffffffaa40
READ of size 8 at 0x5030003bf5d0 thread T0
#0 0x555555ad433f in mprog_greet_trigger(char_data*) /home/deios/afkmud/afkmud251/afkmud/src/mud_prog.cpp:3745
#1 0x555555761dfe in move_char(char_data*, exit_data*, int, int, bool) /home/deios/afkmud/afkmud251/afkmud/src/act_move.cpp:1136
#2 0x555555955573 in interpret(char_data*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /home/deios/afkmud/afkmud251/afkmud/src/commands.cpp:815
#3 0x555555948abe in process_input() /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:864
#4 0x555555948d77 in game_loop() /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:937
#5 0x55555571f636 in main /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:1334
#6 0x7ffff702a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#7 0x7ffff702a28a in __libc_start_main_impl ../csu/libc-start.c:360
#8 0x555555724f74 in _start (/home/deios/afkmud/afkmud251/afkmud/src/afkmud+0x1d0f74) (BuildId: 6bed51a41f25b0a1e70cf3fbea8cda10635e6694)
0x5030003bf5d0 is located 16 bytes inside of 24-byte region [0x5030003bf5c0,0x5030003bf5d8)
freed by thread T0 here:
#0 0x7ffff78ff5e8 in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:164
#1 0x555555913252 in std::__new_allocator<std::_List_node<char_data*> >::deallocate(std::_List_node<char_data*>*, unsigned long) /usr/include/c++/13/bits/new_allocator.h:172
#2 0x555555913252 in std::allocator<std::_List_node<char_data*> >::deallocate(std::_List_node<char_data*>*, unsigned long) /usr/include/c++/13/bits/allocator.h:210
#3 0x555555913252 in std::allocator_traits<std::allocator<std::_List_node<char_data*> > >::deallocate(std::allocator<std::_List_node<char_data*> >&, std::_List_node<char_data*>*, unsigned long) /usr/include/c++/13/bits/alloc_traits.h:517
#4 0x555555913252 in std::__cxx11::_List_base<char_data*, std::allocator<char_data*> >::_M_put_node(std::_List_node<char_data*>*) /usr/include/c++/13/bits/stl_list.h:522
#5 0x555555913252 in std::__cxx11::_List_base<char_data*, std::allocator<char_data*> >::_M_clear() /usr/include/c++/13/bits/list.tcc:81
#6 0x5555558ff890 in std::__cxx11::_List_base<char_data*, std::allocator<char_data*> >::~_List_base() /usr/include/c++/13/bits/stl_list.h:575
#7 0x5555558ff890 in std::__cxx11::list<char_data*, std::allocator<char_data*> >::~list() /usr/include/c++/13/bits/stl_list.h:903
#8 0x5555558ff890 in std::__cxx11::list<char_data*, std::allocator<char_data*> >::remove[abi:__cxx20](char_data* const&) /usr/include/c++/13/bits/list.tcc:363
#9 0x55555590a5f8 in char_data::from_room() /home/deios/afkmud/afkmud251/afkmud/src/character.cpp:2433
#10 0x555555b3c392 in leave_map(char_data*, char_data*, room_index*) /home/deios/afkmud/afkmud251/afkmud/src/overland.cpp:2985
#11 0x555555ab458d in do_mptrlook /home/deios/afkmud/afkmud251/afkmud/src/mud_comm.cpp:4435
#12 0x555555955573 in interpret(char_data*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /home/deios/afkmud/afkmud251/afkmud/src/commands.cpp:815
#13 0x555555ac7b80 in mprog_do_command(char*, char_data*, char_data*, obj_data*, char_data*, obj_data*, char_data*, bool, bool) /home/deios/afkmud/afkmud251/afkmud/src/mud_prog.cpp:2754
#14 0x555555acb95f in mprog_driver(char*, char_data*, char_data*, obj_data*, char_data*, obj_data*, bool) /home/deios/afkmud/afkmud251/afkmud/src/mud_prog.cpp:2433
#15 0x555555ad367d in mprog_percent_check(char_data*, char_data*, obj_data*, char_data*, obj_data*, int) /home/deios/afkmud/afkmud251/afkmud/src/mud_prog.cpp:3232
#16 0x555555ad45ac in mprog_greet_trigger(char_data*) /home/deios/afkmud/afkmud251/afkmud/src/mud_prog.cpp:3770
#17 0x555555761dfe in move_char(char_data*, exit_data*, int, int, bool) /home/deios/afkmud/afkmud251/afkmud/src/act_move.cpp:1136
#18 0x555555955573 in interpret(char_data*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /home/deios/afkmud/afkmud251/afkmud/src/commands.cpp:815
#19 0x555555948abe in process_input() /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:864
#20 0x555555948d77 in game_loop() /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:937
#21 0x55555571f636 in main /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:1334
#22 0x7ffff702a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#23 0x7ffff702a28a in __libc_start_main_impl ../csu/libc-start.c:360
#24 0x555555724f74 in _start (/home/deios/afkmud/afkmud251/afkmud/src/afkmud+0x1d0f74) (BuildId: 6bed51a41f25b0a1e70cf3fbea8cda10635e6694)
previously allocated by thread T0 here:
#0 0x7ffff78fe548 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:95
#1 0x555555907b5f in std::__new_allocator<std::_List_node<char_data*> >::allocate(unsigned long, void const*) /usr/include/c++/13/bits/new_allocator.h:151
#2 0x555555907b5f in std::allocator<std::_List_node<char_data*> >::allocate(unsigned long) /usr/include/c++/13/bits/allocator.h:198
#3 0x555555907b5f in std::allocator_traits<std::allocator<std::_List_node<char_data*> > >::allocate(std::allocator<std::_List_node<char_data*> >&, unsigned long) /usr/include/c++/13/bits/alloc_traits.h:482
#4 0x555555907b5f in std::__cxx11::_List_base<char_data*, std::allocator<char_data*> >::_M_get_node() /usr/include/c++/13/bits/stl_list.h:518
#5 0x555555907b5f in std::_List_node<char_data*>* std::__cxx11::list<char_data*, std::allocator<char_data*> >::_M_create_node<char_data*>(char_data*&&) /usr/include/c++/13/bits/stl_list.h:710
#6 0x555555907b5f in void std::__cxx11::list<char_data*, std::allocator<char_data*> >::_M_insert<char_data*>(std::_List_iterator<char_data*>, char_data*&&) /usr/include/c++/13/bits/stl_list.h:2005
#7 0x555555907b5f in std::__cxx11::list<char_data*, std::allocator<char_data*> >::push_back(char_data*&&) /usr/include/c++/13/bits/stl_list.h:1311
#8 0x555555907b5f in char_data::to_room(room_index*) /home/deios/afkmud/afkmud251/afkmud/src/character.cpp:2478
#9 0x555555760ea0 in move_char(char_data*, exit_data*, int, int, bool) /home/deios/afkmud/afkmud251/afkmud/src/act_move.cpp:922
#10 0x555555955573 in interpret(char_data*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) /home/deios/afkmud/afkmud251/afkmud/src/commands.cpp:815
#11 0x555555948abe in process_input() /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:864
#12 0x555555948d77 in game_loop() /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:937
#13 0x55555571f636 in main /home/deios/afkmud/afkmud251/afkmud/src/comm.cpp:1334
#14 0x7ffff702a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#15 0x7ffff702a28a in __libc_start_main_impl ../csu/libc-start.c:360
#16 0x555555724f74 in _start (/home/deios/afkmud/afkmud251/afkmud/src/afkmud+0x1d0f74) (BuildId: 6bed51a41f25b0a1e70cf3fbea8cda10635e6694)
SUMMARY: AddressSanitizer: heap-use-after-free /home/deios/afkmud/afkmud251/afkmud/src/mud_prog.cpp:3745 in mprog_greet_trigger(char_data*)
Shadow bytes around the buggy address:
0x5030003bf300: fd fd fa fa fd fd fd fd fa fa fd fd fd fa fa fa
0x5030003bf380: fd fd fd fd fa fa fd fd fd fd fa fa fd fd fd fd
0x5030003bf400: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
0x5030003bf480: fd fa fa fa fd fd fd fa fa fa fd fd fd fd fa fa
0x5030003bf500: fd fd fd fd fa fa 00 00 00 07 fa fa 00 00 00 fa
=>0x5030003bf580: fa fa 00 00 00 fa fa fa fd fd[fd]fa fa fa fd fd
0x5030003bf600: fd fd fa fa fd fd fd fd fa fa 00 00 00 00 fa fa
0x5030003bf680: 00 00 00 fa fa fa 00 00 00 fa fa fa fd fd fd fd
0x5030003bf700: fa fa fd fd fd fa fa fa fd fd fd fd fa fa fd fd
0x5030003bf780: fd fd fa fa fd fd fd fd fa fa fd fd fd fa fa fa
0x5030003bf800: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd 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
==30548==ABORTING
I seem to have been wrong about the goto issue. It think it was an issue with the iterator. The vnum 2927 has 2 mptrlook programs. I am guessing the second one could not find vch or vch->in_room. I managed to fix this by modifying the loop slightly but I haven't done a lot of testing. That room at least works now.
void mprog_greet_trigger( char_data * ch )
{
if( !ch->in_room )
{
bug( "%s: ch '%s' not in room. Transferring to Limbo.", __func__, ch->name );
if( !ch->to_room( get_room_index( ROOM_VNUM_LIMBO ) ) )
log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __func__, __LINE__ );
return;
}
list<char_data *> people_copy(ch->in_room->people.begin(), ch->in_room->people.end());
for (char_data *vmob : people_copy)
{
if (ch == vmob)
continue;
// Check if vmob is still valid and in the same room
if (!vmob || !vmob->in_room || ch->in_room != vmob->in_room)
continue;
/*
* Don't let a mob trigger itself, nor one instance of a mob
* trigger another instance.
*/
if( ch->isnpc( ) && ch->pIndexData == vmob->pIndexData )
continue;
// Rest of mprog_greet_trigger is the same