MihailRis/VoxelEngine-Cpp

Сохранение региона крашится?!

Closed this issue · 1 comments

Опишите ошибку
При сохранении региона происходит heap-use-after-free

Для воспроизведения
Шаги для воспроизведения поведения:

  1. Открыть существующий мир (ВНИМАНИЕ: при создании мира не происходит)
  2. Поставить блок где-попало
  3. Нажать Esc и кнопку Save And Quit
  4. См. ошибку

Ожидаемое поведение
Выход и сохранение

Скриншоты

[I] 2024/06/08 21:51:49.256+0300 [               world] world version: 0.22
[I] 2024/06/08 21:52:03.290+0300 [       level-control] writing world
=================================================================
==45497==ERROR: AddressSanitizer: heap-use-after-free on address 0x616000194694 at pc 0x0000006702e7 bp 0x7fff6ac845d0 sp 0x7fff6ac845c8
WRITE of size 1 at 0x616000194694 thread T0
    #0 0x6702e6 in operator() /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:206
    #1 0x6702e6 in _M_dispose /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/shared_ptr_base.h:527
    #2 0x67a655 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/shared_ptr_base.h:346
    #3 0x67a655 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/shared_ptr_base.h:317
    #4 0x67a655 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/shared_ptr_base.h:1071
    #5 0x67a655 in std::__shared_ptr<regfile, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/shared_ptr_base.h:1524
    #6 0x67a655 in std::shared_ptr<regfile>::~shared_ptr() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/shared_ptr.h:175
    #7 0x67a655 in WorldRegions::writeRegion(int, int, int, WorldRegion*) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:279
    #8 0x67ac18 in WorldRegions::writeRegions(int) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:321
    #9 0x67ada4 in WorldRegions::write() /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:462
    #10 0x6701b4 in WorldFiles::write(World const*, Content const*) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldFiles.cpp:82
    #11 0xa619ed in World::write(Level*) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/world/World.cpp:62
    #12 0x90cf80 in LevelController::saveWorld() /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/logic/LevelController.cpp:57
    #13 0x94192c in l_close_world /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/logic/scripting/lua/libcore.cpp:54
    #14 0x94192c in lua_wrap_errors<l_close_world> /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/logic/scripting/lua/lua_commons.hpp:21
    #15 0x7f90a2c90a35  (/nix/store/iq8s1f6d5wjwy4k7dm24qa4jpa3iby54-luajit-2.1.1693350652/lib/libluajit-5.1.so.2+0xba35)
    #16 0x7f90a2cebafb in lua_pcall (/nix/store/iq8s1f6d5wjwy4k7dm24qa4jpa3iby54-luajit-2.1.1693350652/lib/libluajit-5.1.so.2+0x66afb)
    #17 0x920bc7 in lua::LuaState::callNoThrow(int) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/logic/scripting/lua/LuaState.cpp:168
    #18 0x86331d in std::function<void (gui::GUI*)>::operator()(gui::GUI*) const /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/std_function.h:591
    #19 0x86331d in gui::ActionsSet::notify(gui::GUI*) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/graphics/ui/elements/UINode.hpp:38
    #20 0x86331d in gui::UINode::mouseRelease(gui::GUI*, int, int) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/graphics/ui/elements/UINode.cpp:91
    #21 0x7f7154 in gui::GUI::actMouse(float) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/graphics/ui/GUI.cpp:135
    #22 0x7f996d in gui::GUI::act(float, Viewport const&) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/graphics/ui/GUI.cpp:185
    #23 0x6231ba in Engine::mainloop() /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/engine.cpp:165
    #24 0x49598b in main /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/voxel_engine.cpp:27
    #25 0x7f90a243d10d in __libc_start_call_main (/nix/store/k7zgvzp2r31zkg9xqgjim7mbknryv6bs-glibc-2.39-52/lib/libc.so.6+0x2a10d) (BuildId: bc8ec5f3ac2561de8f08b232685038c7167bf4b7)
    #26 0x7f90a243d1c8 in __libc_start_main_alias_1 (/nix/store/k7zgvzp2r31zkg9xqgjim7mbknryv6bs-glibc-2.39-52/lib/libc.so.6+0x2a1c8) (BuildId: bc8ec5f3ac2561de8f08b232685038c7167bf4b7)
    #27 0x49f794 in _start (/mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/build/VoxelEngine+0x49f794)

0x616000194694 is located 532 bytes inside of 536-byte region [0x616000194480,0x616000194698)
freed by thread T0 here:
    #0 0x7f90a30dda78 in operator delete(void*, unsigned long) (/nix/store/xvzz97yk73hw03v5dhhz3j47ggwf1yq1-gcc-13.2.0-lib/lib/libasan.so.8+0xdda78)
    #1 0x67262c in std::default_delete<regfile>::operator()(regfile*) const /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/unique_ptr.h:99
    #2 0x67262c in std::unique_ptr<regfile, std::default_delete<regfile> >::~unique_ptr() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/unique_ptr.h:404
    #3 0x67262c in std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >::~pair() /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/stl_pair.h:187
    #4 0x67262c in void std::__new_allocator<std::__detail::_Hash_node<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, true> >::destroy<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > > >(std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >*) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/new_allocator.h:194
    #5 0x67262c in void std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, true> > >::destroy<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > > >(std::allocator<std::__detail::_Hash_node<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, true> >&, std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >*) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/alloc_traits.h:557
    #6 0x67262c in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, true> > >::_M_deallocate_node(std::__detail::_Hash_node<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, true>*) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/hashtable_policy.h:2020
    #7 0x67262c in std::_Hashtable<glm::vec<3, int, (glm::qualifier)0>, std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, std::allocator<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > > >, std::__detail::_Select1st, std::equal_to<glm::vec<3, int, (glm::qualifier)0> >, std::hash<glm::vec<3, int, (glm::qualifier)0> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_erase(unsigned long, std::__detail::_Hash_node_base*, std::__detail::_Hash_node<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, true>*) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/hashtable.h:2338
    #8 0x67262c in std::_Hashtable<glm::vec<3, int, (glm::qualifier)0>, std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, std::allocator<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > > >, std::__detail::_Select1st, std::equal_to<glm::vec<3, int, (glm::qualifier)0> >, std::hash<glm::vec<3, int, (glm::qualifier)0> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_erase(std::integral_constant<bool, true>, glm::vec<3, int, (glm::qualifier)0> const&) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/hashtable.h:2381
    #9 0x67262c in std::_Hashtable<glm::vec<3, int, (glm::qualifier)0>, std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > >, std::allocator<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > > >, std::__detail::_Select1st, std::equal_to<glm::vec<3, int, (glm::qualifier)0> >, std::hash<glm::vec<3, int, (glm::qualifier)0> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::erase(glm::vec<3, int, (glm::qualifier)0> const&) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/hashtable.h:984
    #10 0x67262c in std::unordered_map<glm::vec<3, int, (glm::qualifier)0>, std::unique_ptr<regfile, std::default_delete<regfile> >, std::hash<glm::vec<3, int, (glm::qualifier)0> >, std::equal_to<glm::vec<3, int, (glm::qualifier)0> >, std::allocator<std::pair<glm::vec<3, int, (glm::qualifier)0> const, std::unique_ptr<regfile, std::default_delete<regfile> > > > >::erase(glm::vec<3, int, (glm::qualifier)0> const&) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/unordered_map.h:770
    #11 0x67262c in WorldRegions::closeRegFile(glm::vec<3, int, (glm::qualifier)0>) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:212

previously allocated by thread T0 here:
    #0 0x7f90a30dcb78 in operator new(unsigned long) (/nix/store/xvzz97yk73hw03v5dhhz3j47ggwf1yq1-gcc-13.2.0-lib/lib/libasan.so.8+0xdcb78)
    #1 0x676e41 in std::__detail::_MakeUniq<regfile>::__single_object std::make_unique<regfile, std::filesystem::__cxx11::path&>(std::filesystem::__cxx11::path&) /nix/store/14c6s4xzhy14i2b05s00rjns2j93gzz4-gcc-13.2.0/include/c++/13.2.0/bits/unique_ptr.h:1070
    #2 0x676e41 in WorldRegions::createRegFile(glm::vec<3, int, (glm::qualifier)0>) /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:261

SUMMARY: AddressSanitizer: heap-use-after-free /mnt/Dev/Tools/voxel-engine-cpp-launcher/versions/Git/src/files/WorldRegions.cpp:206 in operator()
Shadow bytes around the buggy address:
  0x616000194400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x616000194480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x616000194500: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x616000194580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x616000194600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x616000194680: fd fd[fd]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x616000194700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x616000194780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x616000194800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x616000194880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x616000194900: 00 00 00 00 00 00 00 00 00 00 00 00 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
==45497==ABORTING

Техническая информация (заполните следующую информацию):

  • ОС: NixOS 24.05.20240504.d325602 (Uakari) x86_64
  • Версия: 166c340

Дополнительный контекст
Чтобы запустить на NixOS, прешлось убирать проверку GLEW на ошибки, это проблема Wayland.
Мои расследования превели меня сюда:

void WorldRegions::writeRegion(int x, int z, int layer, WorldRegion* entry){
    fs::path filename = layers[layer].folder/getRegionFilename(x, z);

    glm::ivec3 regcoord(x, z, layer);
    //                       V Вызов getRegFile, там вызовется useRegFile
    if (auto regfile = getRegFile(regcoord, false)) {
        fetchChunks(entry, x, z, regfile.get());

        std::lock_guard lock(regFilesMutex);
        //   V Вызов closeRegFile
        closeRegFile(regcoord);
       // Здесь regfile shared_ptr дропается, вызывается deleter
    }
    // ...
}

useRegFile:

std::shared_ptr<regfile> WorldRegions::useRegFile(glm::ivec3 coord) {
    auto* file = openRegFiles[coord].get();
    file->inUse = true;
    return std::shared_ptr<regfile>(file, [this](regfile* ptr) {
        // V Здесь будет heap-use-after-free, если shared_ptr будет жить дольше, чем ptr
        ptr->inUse = false;
        regFilesCv.notify_one();
    });
}

closeRegFile:

void WorldRegions::closeRegFile(glm::ivec3 coord) {
    //   V Удаление файла региона, указатель на него теперь будет смертелен
    openRegFiles.erase(coord);
    regFilesCv.notify_one();
}

openRegFiles:

// Удаление происходит из-за того, что openRegFiles - карта unique_ptr
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;

То же самое происходит при добавлении контент-паков