AFKMud icon indicating copy to clipboard operation
AFKMud copied to clipboard

heap-use-after-free

Open windu-ant opened this issue 11 months ago • 1 comments

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

windu-ant avatar Jan 30 '25 05:01 windu-ant

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

windu-ant avatar Jan 31 '25 00:01 windu-ant