Skip to content

Conversation

@AMS21
Copy link
Contributor

@AMS21 AMS21 commented Nov 13, 2025

Since members are destroyed in reverse order of declaration, previously the CUIDebugger was destructed before CUIFocusSystem which in it's destructor called CUIDebugger::Unregister leading to a use-after-free.

Since this happens during exiting the impact is probably very minimal but the fix is easy enough.

ASAN report
AddressSanitizer: heap-use-after-free on address 0x7c2fca46d690 at pc 0x7fffcd08612f bp 0x7fffffffc6d0 sp 0x7fffffffc6c0
READ of size 8 at 0x7c2fca46d690 thread T0
    #0 0x7fffcd08612e in bool __gnu_cxx::__ops::_Iter_equals_val<CUIDebuggable* const>::operator()<__gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > > >(__gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >) /usr/include/c++/15.2.1/bits/predefined_ops.h:270
    #1 0x7fffcd0862b1 in __gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > > std::__find_if<__gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >, __gnu_cxx::__ops::_Iter_equals_val<CUIDebuggable* const> >(__gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >, __gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >, __gnu_cxx::__ops::_Iter_equals_val<CUIDebuggable* const>) /usr/include/c++/15.2.1/bits/stl_algobase.h:2095
    #2 0x7fffcd08641d in __gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > > std::find<__gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >, CUIDebuggable*>(__gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >, __gnu_cxx::__normal_iterator<CUIDebuggable**, std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> > >, CUIDebuggable* const&) /usr/include/c++/15.2.1/bits/stl_algo.h:3895
    #3 0x7fffcd0844c1 in CUIDebugger::Unregister(CUIDebuggable*) /mnt/data/dev/xray-16/src/xrUICore/ui_debug.cpp:33
    #4 0x7fffcd0847b1 in CUIDebuggable::UnregisterDebuggable() /mnt/data/dev/xray-16/src/xrUICore/ui_debug.cpp:20
    #5 0x7fffcd084822 in CUIDebuggable::~CUIDebuggable() /mnt/data/dev/xray-16/src/xrUICore/ui_debug.cpp:10
    #6 0x7fffcd071d8d in CUIFocusSystem::~CUIFocusSystem() /mnt/data/dev/xray-16/src/xrUICore/ui_focus.h:48
    #7 0x7fffcd065318 in UICore::~UICore() /mnt/data/dev/xray-16/src/xrUICore/ui_base.cpp:249
    #8 0x7fffe1383042 in xr_special_free<true, UICore>::operator()(UICore*&) /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:116
    #9 0x7fffe1383190 in void xr_delete<UICore>(UICore*&) /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:143
    #10 0x7fffe1378f5a in CGamePersistent::OnAppEnd() /mnt/data/dev/xray-16/src/xrGame/GamePersistent.cpp:151
    #11 0x7fffd1685174 in CApplication::~CApplication() /mnt/data/dev/xray-16/src/xrEngine/x_ray.cpp:318
    #12 0x55555555b517 in entry_point(char const*) /mnt/data/dev/xray-16/src/xr_3da/entry_point.cpp:54
    #13 0x55555555b8ed in main /mnt/data/dev/xray-16/src/xr_3da/entry_point.cpp:104
    #14 0x7fffcf027b8a  (/usr/lib/libc.so.6+0x27b8a) (BuildId: 3fb5bf3586fec17ba65a16ec9a3132455897d306)
    #15 0x7fffcf027c4a in __libc_start_main (/usr/lib/libc.so.6+0x27c4a) (BuildId: 3fb5bf3586fec17ba65a16ec9a3132455897d306)
    #16 0x55555555b304 in _start (/mnt/data/dev/xray-16/bin/x86_64/Debug/xr_3da+0x7304) (BuildId: a42307e2056b24dd7d40950015579916511720c5)

0x7c2fca46d690 is located 0 bytes inside of 32-byte region [0x7c2fca46d690,0x7c2fca46d6b0)
freed by thread T0 here:
    #0 0x7ffff795103d in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:51
    #1 0x7fffd048b447 in xrMemory::mem_free(void*) /mnt/data/dev/xray-16/src/xrCore/xrMemory.cpp:260
    #2 0x7fffcd06ed4b in void xr_free<CUIDebuggable*>(CUIDebuggable**&) /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:105
    #3 0x7fffcd06ee72 in xalloc<CUIDebuggable*>::deallocate(CUIDebuggable**, unsigned long) /mnt/data/dev/xray-16/src/xrCore/Memory/xalloc.h:41
    #4 0x7fffcd06ee72 in std::allocator_traits<xalloc<CUIDebuggable*> >::deallocate(xalloc<CUIDebuggable*>&, CUIDebuggable**, unsigned long) /usr/include/c++/15.2.1/bits/alloc_traits.h:417
    #5 0x7fffcd06ee72 in std::_Vector_base<CUIDebuggable*, xalloc<CUIDebuggable*> >::_M_deallocate(CUIDebuggable**, unsigned long) /usr/include/c++/15.2.1/bits/stl_vector.h:396
    #6 0x7fffcd06ee72 in std::_Vector_base<CUIDebuggable*, xalloc<CUIDebuggable*> >::~_Vector_base() /usr/include/c++/15.2.1/bits/stl_vector.h:375
    #7 0x7fffcd06ef87 in std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> >::~vector() /usr/include/c++/15.2.1/bits/stl_vector.h:805
    #8 0x7fffcd0818d8 in CUIDebugger::~CUIDebugger() (/mnt/data/dev/xray-16/bin/x86_64/Debug/xrUICore.so+0x8818d8) (BuildId: 0de8ad46c626c8c422105b8b9cbdd8c7222b89f3)
    #9 0x7fffcd065303 in UICore::~UICore() /mnt/data/dev/xray-16/src/xrUICore/ui_base.cpp:249
    #10 0x7fffe1383042 in xr_special_free<true, UICore>::operator()(UICore*&) /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:116
    #11 0x7fffe1383190 in void xr_delete<UICore>(UICore*&) /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:143
    #12 0x7fffe1378f5a in CGamePersistent::OnAppEnd() /mnt/data/dev/xray-16/src/xrGame/GamePersistent.cpp:151
    #13 0x7fffd1685174 in CApplication::~CApplication() /mnt/data/dev/xray-16/src/xrEngine/x_ray.cpp:318
    #14 0x55555555b517 in entry_point(char const*) /mnt/data/dev/xray-16/src/xr_3da/entry_point.cpp:54
    #15 0x55555555b8ed in main /mnt/data/dev/xray-16/src/xr_3da/entry_point.cpp:104
    #16 0x7fffcf027b8a  (/usr/lib/libc.so.6+0x27b8a) (BuildId: 3fb5bf3586fec17ba65a16ec9a3132455897d306)
    #17 0x7fffffffd5aa  ([stack]+0x795aa)

previously allocated by thread T0 here:
    #0 0x7ffff7952345 in malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:67
    #1 0x7fffd048b3cf in xrMemory::mem_alloc(unsigned long) /mnt/data/dev/xray-16/src/xrCore/xrMemory.cpp:202
    #2 0x7fffcd087014 in CUIDebuggable** xr_alloc<CUIDebuggable*>(unsigned long) /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:97
    #3 0x7fffcd087675 in xalloc<CUIDebuggable*>::allocate(unsigned long, void const*) /mnt/data/dev/xray-16/src/xrCore/Memory/xalloc.h:40
    #4 0x7fffcd087675 in std::allocator_traits<xalloc<CUIDebuggable*> >::allocate(xalloc<CUIDebuggable*>&, unsigned long) /usr/include/c++/15.2.1/bits/alloc_traits.h:385
    #5 0x7fffcd087675 in std::_Vector_base<CUIDebuggable*, xalloc<CUIDebuggable*> >::_M_allocate(unsigned long) /usr/include/c++/15.2.1/bits/stl_vector.h:387
    #6 0x7fffcd087675 in void std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> >::_M_realloc_append<CUIDebuggable*&>(CUIDebuggable*&) /usr/include/c++/15.2.1/bits/vector.tcc:572
    #7 0x7fffcd087b80 in CUIDebuggable*& std::vector<CUIDebuggable*, xalloc<CUIDebuggable*> >::emplace_back<CUIDebuggable*&>(CUIDebuggable*&) /usr/include/c++/15.2.1/bits/vector.tcc:123
    #8 0x7fffcd08428e in CUIDebugger::Register(CUIDebuggable*) /mnt/data/dev/xray-16/src/xrUICore/ui_debug.cpp:26
    #9 0x7fffcd08436f in CUIDebuggable::RegisterDebuggable() /mnt/data/dev/xray-16/src/xrUICore/ui_debug.cpp:15
    #10 0x7fffe2be229d in CDialogHolder::CDialogHolder() /mnt/data/dev/xray-16/src/xrGame/UIDialogHolder.cpp:29
    #11 0x7fffe2ca55c2 in CUIGameCustom::CUIGameCustom() /mnt/data/dev/xray-16/src/xrGame/UIGameCustom.cpp:30
    #12 0x7fffe2cf539d in CUIGameSP::CUIGameSP() /mnt/data/dev/xray-16/src/xrGame/UIGameSP.cpp:25
    #13 0x7fffe41179b8 in CUIGameSP* xr_new<CUIGameSP>() /mnt/data/dev/xray-16/src/xrCore/xrMemory.h:135
    #14 0x7fffe41179dc in CObjectItemSingle<CUIGameSP, true>::client_object() const /mnt/data/dev/xray-16/src/xrServerEntities/object_item_single_inline.h:42
    #15 0x7fffe2f99cca in CObjectFactory::client_object(unsigned long const&) const /mnt/data/dev/xray-16/src/xrServerEntities/object_factory_inline.h:127
    #16 0x7fffe2f987c4 in xrFactory_Create /mnt/data/dev/xray-16/src/xrGame/xrGame.cpp:31
    #17 0x7fffe131d56a in game_cl_Single::createGameUI() /mnt/data/dev/xray-16/src/xrGame/game_cl_single.cpp:21
    #18 0x7fffe17616cc in CHUDManager::Load() /mnt/data/dev/xray-16/src/xrGame/HUDManager.cpp:214
    #19 0x7fffe19f4f7f in CLevel::net_start_client6() /mnt/data/dev/xray-16/src/xrGame/Level_network_start_client.cpp:245
    #20 0x7fffd16d2bee in fastdelegate::FastDelegate<bool ()>::operator()() const /mnt/data/dev/xray-16/src/xrCore/fastdelegate.h:766
    #21 0x7fffd16cd6b5 in CRenderDevice::BeforeFrame() /mnt/data/dev/xray-16/src/xrEngine/device.cpp:177
    #22 0x7fffd16cf2ff in CRenderDevice::ProcessFrame() /mnt/data/dev/xray-16/src/xrEngine/device.cpp:265
    #23 0x7fffd168470e in CApplication::Run() /mnt/data/dev/xray-16/src/xrEngine/x_ray.cpp:433
    #24 0x55555555b4d5 in entry_point(char const*) /mnt/data/dev/xray-16/src/xr_3da/entry_point.cpp:53
    #25 0x55555555b8ed in main /mnt/data/dev/xray-16/src/xr_3da/entry_point.cpp:104
    #26 0x7fffcf027b8a  (/usr/lib/libc.so.6+0x27b8a) (BuildId: 3fb5bf3586fec17ba65a16ec9a3132455897d306)
    #27 0x7fffffffd5aa  ([stack]+0x795aa)

SUMMARY: AddressSanitizer: heap-use-after-free /mnt/data/dev/xray-16/src/xrUICore/ui_debug.cpp:33 in CUIDebugger::Unregister(CUIDebuggable*)
Shadow bytes around the buggy address:
  0x7c2fca46d400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7c2fca46d480: 00 00 00 00 fa fa 00 00 00 00 fa fa fa fa fa fa
  0x7c2fca46d500: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa fa fa
  0x7c2fca46d580: fa fa fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
  0x7c2fca46d600: fa fa fa fa fa fa 00 00 00 fa fa fa 00 00 00 00
=>0x7c2fca46d680: fa fa[fd]fd fd fd fa fa 00 00 00 00 fa fa 00 00
  0x7c2fca46d700: 00 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7c2fca46d780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x7c2fca46d800: fa fa fa fa fa fa fa fa 00 00 00 00 fa fa fa fa
  0x7c2fca46d880: fa fa fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
  0x7c2fca46d900: fa fa fa fa fa fa fa fa fa fa fa fa 00 00 00 00
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

@github-actions github-actions bot added the UI label Nov 13, 2025
@Xottab-DUTY Xottab-DUTY merged commit 756cbb9 into OpenXRay:dev Nov 13, 2025
46 checks passed
@github-project-automation github-project-automation bot moved this to Done in Roadmap Nov 13, 2025
@Xottab-DUTY Xottab-DUTY added the Bug The issue in the run-time. label Nov 13, 2025
@Xottab-DUTY Xottab-DUTY removed this from Roadmap Nov 13, 2025
@AMS21 AMS21 deleted the debugger_exit_uaf branch November 13, 2025 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug The issue in the run-time. UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants