Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heap use after free in Squirrel delayed memory deallocation when AI deallocated #9267

Closed
JGRennison opened this issue May 14, 2021 · 3 comments · Fixed by #9275
Closed

Heap use after free in Squirrel delayed memory deallocation when AI deallocated #9267

JGRennison opened this issue May 14, 2021 · 3 comments · Fixed by #9275

Comments

@JGRennison
Copy link
Contributor

Version of OpenTTD

1da0ba9, Linux, SDL2
Presumably since 47a99bb, 44d1b96

Expected result

No heap use after frees occur.

Actual result

Heap use after free (detected by AddressSanitizer) in Squirrel delayed memory deallocation when AI deallocated.

Details
=================================================================
==887579==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b0000b7aa0 at pc 0x5614b1462eaa bp 0x7f04e81e82b0 sp 0x7f04e81e82a0
READ of size 8 at 0x60b0000b7aa0 thread T3 (ottd:game)
  #0 0x5614b1462ea9 in SQObjectPtr::~SQObjectPtr() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqobject.h:275
  #1 0x5614b148c3e6 in SQInstance::~SQInstance() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.cpp:175
  #2 0x5614b148f4b6 in SQInstance::FinalFree() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.h:147
  #3 0x5614b151a18a in SQSharedState::DelayFinalFree(SQCollectable*) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqstate.cpp:251
  #4 0x5614b148ece8 in SQInstance::Release() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.h:142
  #5 0x5614b1518a1c in SQSharedState::~SQSharedState() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqstate.cpp:207
  #6 0x5614b143c03d in sq_close(SQVM*) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqapi.cpp:132
  #7 0x5614b1416731 in Squirrel::Uninitialize() /home/jgr/misc/openttd-2/src/script/squirrel.cpp:759
  #8 0x5614b141654d in Squirrel::~Squirrel() /home/jgr/misc/openttd-2/src/script/squirrel.cpp:750
  #9 0x5614b13d9b5d in ScriptInstance::~ScriptInstance() /home/jgr/misc/openttd-2/src/script/script_instance.cpp:142
  #10 0x5614b16fc78f in AIInstance::~AIInstance() /home/jgr/misc/openttd-2/src/ai/ai_instance.hpp:16
  #11 0x5614b16fc7d9 in AIInstance::~AIInstance() /home/jgr/misc/openttd-2/src/ai/ai_instance.hpp:16
  #12 0x5614b15b1a09 in AI::Stop(Owner) /home/jgr/misc/openttd-2/src/ai/ai_core.cpp:110
  #13 0x5614b15b283a in AI::KillAll() /home/jgr/misc/openttd-2/src/ai/ai_core.cpp:157
  #14 0x5614b2fbf0e4 in SwitchToMode(SwitchMode) /home/jgr/misc/openttd-2/src/openttd.cpp:1022
  #15 0x5614b2fc8cff in GameLoop() /home/jgr/misc/openttd-2/src/openttd.cpp:1478
  #16 0x5614b2106684 in VideoDriver::GameLoop() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:37
  #17 0x5614b2106980 in VideoDriver::GameThread() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:44
  #18 0x5614b210707a in VideoDriver::GameThreadThunk(VideoDriver*) /home/jgr/misc/openttd-2/src/video/video_driver.cpp:81
  #19 0x5614b210d7de in StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}::operator()(char const*, void (*&&)(VideoDriver*), VideoDriver*&&) const /home/jgr/misc/openttd-2/src/video/../thread.h:54
  #20 0x5614b2110f50 in void std::__invoke_impl<void, StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*>(std::__invoke_other, StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&&&)(VideoDriver*), VideoDriver*&&)#1}, char const*&&, void (*&&)(VideoDriver*), VideoDriver*&&) /usr/include/c++/9/bits/invoke.h:60
  #21 0x5614b2110b0e in _ZSt8__invokeIZ14StartNewThreadIPFvP11VideoDriverEJS2_EEbPSt6threadPKcOT_DpOT0_EUlS8_OS4_OS2_E_JS8_S4_S2_EENSt15__invoke_resultIS9_JDpSB_EE4typeESA_SD_ /usr/include/c++/9/bits/invoke.h:95
  #22 0x5614b2110773 in void std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> >::_M_invoke<0ul, 1ul, 2ul, 3ul>(std::_Index_tuple<0ul, 1ul, 2ul, 3ul>) /usr/include/c++/9/thread:244
  #23 0x5614b21104c0 in std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> >::operator()() /usr/include/c++/9/thread:251
  #24 0x5614b2110476 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> > >::_M_run() /usr/include/c++/9/thread:195
  #25 0x7f059364ed83  (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xd6d83)
  #26 0x7f0593762608 in start_thread /build/glibc-eX1tMB/glibc-2.31/nptl/pthread_create.c:477
  #27 0x7f05929cf292 in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x122292)

0x60b0000b7aa0 is located 0 bytes inside of 104-byte region [0x60b0000b7aa0,0x60b0000b7b08)
freed by thread T3 (ottd:game) here:
  #0 0x7f059406d7cf in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf)
  #1 0x5614b141a13b in ScriptAllocator::Free(void*, unsigned long long) /home/jgr/misc/openttd-2/src/script/squirrel.cpp:149
  #2 0x5614b140f7cf in sq_vm_free(void*, unsigned long long) /home/jgr/misc/openttd-2/src/script/squirrel.cpp:188
  #3 0x5614b148f4c9 in SQInstance::FinalFree() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.h:148
  #4 0x5614b151a18a in SQSharedState::DelayFinalFree(SQCollectable*) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqstate.cpp:251
  #5 0x5614b148ece8 in SQInstance::Release() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.h:142
  #6 0x5614b1518a1c in SQSharedState::~SQSharedState() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqstate.cpp:207
  #7 0x5614b143c03d in sq_close(SQVM*) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqapi.cpp:132
  #8 0x5614b1416731 in Squirrel::Uninitialize() /home/jgr/misc/openttd-2/src/script/squirrel.cpp:759
  #9 0x5614b141654d in Squirrel::~Squirrel() /home/jgr/misc/openttd-2/src/script/squirrel.cpp:750
  #10 0x5614b13d9b5d in ScriptInstance::~ScriptInstance() /home/jgr/misc/openttd-2/src/script/script_instance.cpp:142
  #11 0x5614b16fc78f in AIInstance::~AIInstance() /home/jgr/misc/openttd-2/src/ai/ai_instance.hpp:16
  #12 0x5614b16fc7d9 in AIInstance::~AIInstance() /home/jgr/misc/openttd-2/src/ai/ai_instance.hpp:16
  #13 0x5614b15b1a09 in AI::Stop(Owner) /home/jgr/misc/openttd-2/src/ai/ai_core.cpp:110
  #14 0x5614b15b283a in AI::KillAll() /home/jgr/misc/openttd-2/src/ai/ai_core.cpp:157
  #15 0x5614b2fbf0e4 in SwitchToMode(SwitchMode) /home/jgr/misc/openttd-2/src/openttd.cpp:1022
  #16 0x5614b2fc8cff in GameLoop() /home/jgr/misc/openttd-2/src/openttd.cpp:1478
  #17 0x5614b2106684 in VideoDriver::GameLoop() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:37
  #18 0x5614b2106980 in VideoDriver::GameThread() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:44
  #19 0x5614b210707a in VideoDriver::GameThreadThunk(VideoDriver*) /home/jgr/misc/openttd-2/src/video/video_driver.cpp:81
  #20 0x5614b210d7de in StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}::operator()(char const*, void (*&&)(VideoDriver*), VideoDriver*&&) const /home/jgr/misc/openttd-2/src/video/../thread.h:54
  #21 0x5614b2110f50 in void std::__invoke_impl<void, StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*>(std::__invoke_other, StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&&&)(VideoDriver*), VideoDriver*&&)#1}, char const*&&, void (*&&)(VideoDriver*), VideoDriver*&&) /usr/include/c++/9/bits/invoke.h:60
  #22 0x5614b2110b0e in _ZSt8__invokeIZ14StartNewThreadIPFvP11VideoDriverEJS2_EEbPSt6threadPKcOT_DpOT0_EUlS8_OS4_OS2_E_JS8_S4_S2_EENSt15__invoke_resultIS9_JDpSB_EE4typeESA_SD_ /usr/include/c++/9/bits/invoke.h:95
  #23 0x5614b2110773 in void std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> >::_M_invoke<0ul, 1ul, 2ul, 3ul>(std::_Index_tuple<0ul, 1ul, 2ul, 3ul>) /usr/include/c++/9/thread:244
  #24 0x5614b21104c0 in std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> >::operator()() /usr/include/c++/9/thread:251
  #25 0x5614b2110476 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> > >::_M_run() /usr/include/c++/9/thread:195
  #26 0x7f059364ed83  (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xd6d83)

previously allocated by thread T3 (ottd:game) here:
  #0 0x7f059406dbc8 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
  #1 0x5614b1419e52 in ScriptAllocator::Malloc(unsigned long long) /home/jgr/misc/openttd-2/src/script/squirrel.cpp:101
  #2 0x5614b140f717 in sq_vm_malloc(unsigned long long) /home/jgr/misc/openttd-2/src/script/squirrel.cpp:186
  #3 0x5614b148de57 in SQInstance::Create(SQSharedState*, SQClass*) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.h:90
  #4 0x5614b1486e65 in SQClass::CreateInstance() /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqclass.cpp:91
  #5 0x5614b158defe in SQVM::CreateClassInstance(SQClass*, SQObjectPtr&, SQObjectPtr&) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqvm.cpp:1109
  #6 0x5614b155867f in SQVM::Execute(SQObjectPtr&, long long, long long, long long, SQObjectPtr&, unsigned long long, SQVM::ExecutionType) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqvm.cpp:823
  #7 0x5614b1456b3a in sq_resumecatch(SQVM*, int) /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqapi.cpp:1023
  #8 0x5614b1411f42 in Squirrel::Resume(int) /home/jgr/misc/openttd-2/src/script/squirrel.cpp:391
  #9 0x5614b13dee40 in ScriptInstance::GameLoop() /home/jgr/misc/openttd-2/src/script/script_instance.cpp:246
  #10 0x5614b15b1216 in AI::GameLoop() /home/jgr/misc/openttd-2/src/ai/ai_core.cpp:82
  #11 0x5614b2fc81aa in StateGameLoop() /home/jgr/misc/openttd-2/src/openttd.cpp:1394
  #12 0x5614b2fc90c1 in GameLoop() /home/jgr/misc/openttd-2/src/openttd.cpp:1497
  #13 0x5614b2106684 in VideoDriver::GameLoop() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:37
  #14 0x5614b2106980 in VideoDriver::GameThread() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:44
  #15 0x5614b210707a in VideoDriver::GameThreadThunk(VideoDriver*) /home/jgr/misc/openttd-2/src/video/video_driver.cpp:81
  #16 0x5614b210d7de in StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}::operator()(char const*, void (*&&)(VideoDriver*), VideoDriver*&&) const /home/jgr/misc/openttd-2/src/video/../thread.h:54
  #17 0x5614b2110f50 in void std::__invoke_impl<void, StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*>(std::__invoke_other, StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&&&)(VideoDriver*), VideoDriver*&&)#1}, char const*&&, void (*&&)(VideoDriver*), VideoDriver*&&) /usr/include/c++/9/bits/invoke.h:60
  #18 0x5614b2110b0e in _ZSt8__invokeIZ14StartNewThreadIPFvP11VideoDriverEJS2_EEbPSt6threadPKcOT_DpOT0_EUlS8_OS4_OS2_E_JS8_S4_S2_EENSt15__invoke_resultIS9_JDpSB_EE4typeESA_SD_ /usr/include/c++/9/bits/invoke.h:95
  #19 0x5614b2110773 in void std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> >::_M_invoke<0ul, 1ul, 2ul, 3ul>(std::_Index_tuple<0ul, 1ul, 2ul, 3ul>) /usr/include/c++/9/thread:244
  #20 0x5614b21104c0 in std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> >::operator()() /usr/include/c++/9/thread:251
  #21 0x5614b2110476 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&)::{lambda(char const*, void (*&&)(VideoDriver*), VideoDriver*&&)#1}, char const*, void (*)(VideoDriver*), VideoDriver*> > >::_M_run() /usr/include/c++/9/thread:195
  #22 0x7f059364ed83  (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xd6d83)

Thread T3 (ottd:game) created by T0 here:
  #0 0x7f0593f9a805 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x3a805)
  #1 0x7f059364f048 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xd7048)
  #2 0x5614b210d985 in bool StartNewThread<void (*)(VideoDriver*), VideoDriver*>(std::thread*, char const*, void (*&&)(VideoDriver*), VideoDriver*&&) /home/jgr/misc/openttd-2/src/video/../thread.h:49
  #3 0x5614b21074a1 in VideoDriver::StartGameThread() /home/jgr/misc/openttd-2/src/video/video_driver.cpp:87
  #4 0x5614b20e0d3b in VideoDriver_SDL_Base::MainLoop() /home/jgr/misc/openttd-2/src/video/sdl2_v.cpp:657
  #5 0x5614b2fbd6c5 in openttd_main(int, char**) /home/jgr/misc/openttd-2/src/openttd.cpp:833
  #6 0x5614b1d58fbe in main /home/jgr/misc/openttd-2/src/os/unix/unix.cpp:262
  #7 0x7f05928d40b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-use-after-free /home/jgr/misc/openttd-2/src/3rdparty/squirrel/squirrel/sqobject.h:275 in SQObjectPtr::~SQObjectPtr()
Shadow bytes around the buggy address:
0x0c168000ef00: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
0x0c168000ef10: fa fa fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c168000ef20: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c168000ef30: fd fd fd fd fd fd fa fa fa fa fa fa fa fa fd fd
0x0c168000ef40: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa
=>0x0c168000ef50: fa fa fa fa[fd]fd fd fd fd fd fd fd fd fd fd fd
0x0c168000ef60: fd fa fa fa fa fa fa fa fa fa fd fd fd fd fd fd
0x0c168000ef70: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
0x0c168000ef80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa
0x0c168000ef90: fa fa fa fa fa fa fd fd fd fd fd fd fd fd fd fd
0x0c168000efa0: fd fd fd fa fa fa fa fa fa fa fa fa fd fd fd fd
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
Shadow gap:              cc
==887579==ABORTING

Steps to reproduce

Start or load a game with an AI (my testing used NoCab).
Let the AI run for a few minutes so that it can allocate things.
Abandon or exit the game, such that the AI destructor is called.

See also

Original report: JGRennison/OpenTTD-patches#256

@rubidium42
Copy link
Contributor

At least it's since 47a99bb, though no clue yet what in that change causes this. Except that not running the garbage collection makes it work without problems.

@rubidium42
Copy link
Contributor

I fear the order of the objects in the _gc_chain is important for some things in some manner, and that order has been changed. As the place where it does get the heap use after free, is at a location where it previously did not even attempt to free things. The loop before that already ensured everything was freed.

@JGRennison
Copy link
Contributor Author

SQClass::Finalize changes the length of _defaultvalues to 0, but SQInstance::Finalize looks at the length of _defaultvalues of its associated SQClass when finalising SQInstance::_values
The SQInstance destructor implicitly assumes that SQInstance::_values has length 1 as SQInstance uses the array of size 1 flexible array member mechanism.
Assuming a minimum length of 1 in SQInstance::Finalize as in

SQUnsignedInteger nvalues = std::max<SQUnsignedInteger>(1, _class->_defaultvalues.size());

seems to make the problem go away.

rubidium42 added a commit to rubidium42/OpenTTD that referenced this issue May 16, 2021
Due to 47a99bb the order of elements in the garbage collection chain has
changed causing the class to be finalised before the instances of that class.
Since the instance's array of member values depends on the size of the values
in the class, the class finalisation resetting that size to 0 causes not all
finalisations to run, which subsequently causes a heap use after free. So,
just set the SQObjectPtrs to 'null' during the finalisation of the SQClass
so the SQInstance can release all instance variables during its finalisation.
rubidium42 added a commit to rubidium42/OpenTTD that referenced this issue May 16, 2021
Due to 47a99bb the order of elements in the garbage collection chain has
changed causing the class to be finalised before the instances of that class.
Since the instance's array of member values depends on the size of the values
in the class, the class finalisation resetting that size to 0 causes not all
finalisations to run, which subsequently causes a heap use after free. So,
just set the SQObjectPtrs to 'null' during the finalisation of the SQClass
so the SQInstance can release all instance variables during its finalisation.
rubidium42 added a commit that referenced this issue May 16, 2021
Due to 47a99bb the order of elements in the garbage collection chain has
changed causing the class to be finalised before the instances of that class.
Since the instance's array of member values depends on the size of the values
in the class, the class finalisation resetting that size to 0 causes not all
finalisations to run, which subsequently causes a heap use after free. So,
just set the SQObjectPtrs to 'null' during the finalisation of the SQClass
so the SQInstance can release all instance variables during its finalisation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants