View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||
ID | Project | Category | View Status | Date Submitted | Last Update | ||||
---|---|---|---|---|---|---|---|---|---|
0006327 | Spring engine | General | public | 2019-11-03 12:04 | 2019-11-03 13:42 | ||||
Reporter | esainane | ||||||||
Assigned To | Kloot | ||||||||
Priority | normal | Severity | crash | Reproducibility | have not tried | ||||
Status | resolved | Resolution | fixed | ||||||
Product Version | 104.0 +git | ||||||||
Target Version | Fixed in Version | 104.0 +git | |||||||
Summary | 0006327: heap-buffer-overflow in spring 104.0.1-1429-g1add37cca0 | ||||||||
Description | With the upstream built 104.0.1-1429-g1add37cca0 linux spring version, the game crashes somewhere between 3 and 5 minutes into a networked game, with libc complaining that malloc's internal data structures have become corrupted, killing the game. This issue does not seem to appear in a local game. infolog.txt is flooded with 'Error: [Game::ClientReadNet][NETMSG_AICOMMANDS] exception "Unpack failure (type)"' Building a custom version of 104.0.1-1429-g1add37cca0 with -fsanitize=address and -fsanitize=undefined, inserting the line "if (game)" in rts/System/SpringApp.cpp line 651 to prevent the sanitizer from halting the process earlier due to a null pointer dereference in the immediately following "game->KillLua(false);", the address sanitizer detects the following buffer overlow as soon as a networked game starts: ================================================================= ==27185==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6040003e8c3a at pc 0x5590a49b2530 bp 0x7ffd92c1e370 sp 0x7ffd92c1e368 WRITE of size 4 at 0x6040003e8c3a thread T0 (spring-main) #0 0x5590a49b252f in netcode::PackPacket& netcode::PackPacket::operator<< <float>(float const&) /home/user/repo/springrts/rts/System/Net/PackPacket.h:34 #1 0x5590a49b252f in CSelectedUnitsHandler::SendCommandsToUnits(std::vector<int, std::allocator<int> > const&, std::vector<Command, std::allocator<Command> > const&, bool) /home/user/repo/springrts/rts/Game/SelectedUnitsHandler.cpp:1089 #2 0x5590a5dcc1a4 in LuaUnsyncedCtrl::GiveOrderArrayToUnitArray(lua_State*) /home/user/repo/springrts/rts/Lua/LuaUnsyncedCtrl.cpp:2562 0000003 0x5590a89bcff0 in luaD_precall(lua_State*, lua_TValue*, int) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:320 0000004 0x5590a8a0f35d in luaV_execute(lua_State*, int) /home/user/repo/springrts/rts/lib/lua/src/lvm.cpp:613 0000005 0x5590a89bfebc in luaD_call(lua_State*, lua_TValue*, int) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:378 #6 0x5590a89b85eb in luaD_rawrunprotected(lua_State*, void (*)(lua_State*, void*), void*) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:116 #7 0x5590a89c0a93 in luaD_pcall(lua_State*, void (*)(lua_State*, void*), void*, long, long) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:464 #8 0x5590a89a11b8 in lua_pcall(lua_State*, int, int, int) /home/user/repo/springrts/rts/lib/lua/src/lapi.cpp:833 #9 0x5590a89a8982 in luaB_pcall /home/user/repo/springrts/rts/lib/lua/src/lbaselib.cpp:377 0000010 0x5590a89bcff0 in luaD_precall(lua_State*, lua_TValue*, int) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:320 #11 0x5590a8a0f35d in luaV_execute(lua_State*, int) /home/user/repo/springrts/rts/lib/lua/src/lvm.cpp:613 0000012 0x5590a89bfebc in luaD_call(lua_State*, lua_TValue*, int) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:378 0000013 0x5590a89b85eb in luaD_rawrunprotected(lua_State*, void (*)(lua_State*, void*), void*) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:116 0000014 0x5590a89c0a93 in luaD_pcall(lua_State*, void (*)(lua_State*, void*), void*, long, long) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:464 #15 0x5590a89a11b8 in lua_pcall(lua_State*, int, int, int) /home/user/repo/springrts/rts/lib/lua/src/lapi.cpp:833 #16 0x5590a89a8982 in luaB_pcall /home/user/repo/springrts/rts/lib/lua/src/lbaselib.cpp:377 #17 0x5590a89bcff0 in luaD_precall(lua_State*, lua_TValue*, int) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:320 #18 0x5590a8a0f35d in luaV_execute(lua_State*, int) /home/user/repo/springrts/rts/lib/lua/src/lvm.cpp:613 #19 0x5590a89bfebc in luaD_call(lua_State*, lua_TValue*, int) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:378 0000020 0x5590a89b85eb in luaD_rawrunprotected(lua_State*, void (*)(lua_State*, void*), void*) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:116 #21 0x5590a89c0a93 in luaD_pcall(lua_State*, void (*)(lua_State*, void*), void*, long, long) /home/user/repo/springrts/rts/lib/lua/src/ldo.cpp:464 #22 0x5590a89a11b8 in lua_pcall(lua_State*, int, int, int) /home/user/repo/springrts/rts/lib/lua/src/lapi.cpp:833 #23 0x5590a576605d in ScopedLuaCall /home/user/repo/springrts/rts/Lua/LuaHandle.cpp:326 0000024 0x5590a576605d in CLuaHandle::RunCallInTraceback(lua_State*, LuaHashString const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, int, int, bool) /home/user/repo/springrts/rts/Lua/LuaHandle.cpp:412 #25 0x5590a5769ef9 in CLuaHandle::RunCallInTraceback(lua_State*, LuaHashString const&, int, int, int, bool) /home/user/repo/springrts/rts/Lua/LuaHandle.cpp:422 0000026 0x5590a57cb5e6 in CLuaHandle::GameFrame(int) /home/user/repo/springrts/rts/Lua/LuaHandle.cpp:657 0000027 0x5590a795b233 in void IterateEventClientList<std::vector<CEventClient*, std::allocator<CEventClient*> >, void (CEventClient::*)(int), int&>(std::vector<CEventClient*, std::allocator<CEventClient*> >&, void (CEventClient::* const&)(int), int&) /home/user/repo/springrts/rts/System/EventHandler.cpp:453 #28 0x5590a78e69b9 in CEventHandler::GameFrame(int) /home/user/repo/springrts/rts/System/EventHandler.cpp:499 0000029 0x5590a465690e in CGame::SimFrame() /home/user/repo/springrts/rts/Game/Game.cpp:1520 #30 0x5590a5663249 in CGame::ClientReadNet() /home/user/repo/springrts/rts/Net/NetCommands.cpp:562 #31 0x5590a46847fb in CGame::Update() /home/user/repo/springrts/rts/Game/Game.cpp:1076 #32 0x5590a7bbf497 in SpringApp::Update() /home/user/repo/springrts/rts/System/SpringApp.cpp:764 #33 0x5590a7bdc9b2 in SpringApp::Run() /home/user/repo/springrts/rts/System/SpringApp.cpp:803 0000034 0x5590a7aa26a1 in Run(int, char**) /home/user/repo/springrts/rts/System/Main.cpp:43 0000035 0x5590a432e93f in main /home/user/repo/springrts/rts/System/Main.cpp:94 #36 0x7f997e20a09a in __libc_start_main ../csu/libc-start.c:308 #37 0x5590a43fb5f9 in _start (/home/user/Zero-K/engine/linux64/104.0.1-1429-g1add37c/spring+0xdc355f9) 0x6040003e8c3d is located 0 bytes to the right of 45-byte region [0x6040003e8c10,0x6040003e8c3d) allocated by thread T0 (spring-main) here: #0 0x7f9980368ef0 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xeaef0) #1 0x5590a882a970 in netcode::RawPacket::RawPacket(unsigned int) /home/user/repo/springrts/rts/System/Net/RawPacket.h:37 #2 0x5590a882a970 in netcode::PackPacket::PackPacket(unsigned int) /home/user/repo/springrts/rts/System/Net/PackPacket.cpp:15 SUMMARY: AddressSanitizer: heap-buffer-overflow /home/user/repo/springrts/rts/System/Net/PackPacket.h:34 in netcode::PackPacket& netcode::PackPacket::operator<< <float>(float const&) Shadow bytes around the buggy address: 0x0c0880075130: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00 fa 0x0c0880075140: fa fa 00 00 00 00 00 fa fa fa fa fa fa fa fa fa 0x0c0880075150: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 00 0x0c0880075160: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa 0x0c0880075170: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c0880075180: fa fa 00 00 00 00 00[05]fa fa 00 00 00 00 00 fa 0x0c0880075190: fa fa 00 00 00 00 00 03 fa fa 00 00 00 00 00 fa 0x0c08800751a0: fa fa 00 00 00 00 00 fa fa fa fa fa fa fa fa fa 0x0c08800751b0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00 04 0x0c08800751c0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 00 0x0c08800751d0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00 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 ==27185==ABORTING It is my suspicion that similar heap overflows occur repeatedly with network traffic until something that the libc checks is overwritten, at which point the game crashes. This issue does not occur with 104.0.1-1398-g7442945. | ||||||||
Steps To Reproduce | Join a networked game on linux and have an opponent make many commands for a few minutes until the game crashes, or build with -fsanitize=address -fsanitize=undefined to detect more buffer overflows almost instantly. | ||||||||
Additional Information | Example replay: https://zero-k.info/Battles/Detail/790393 Infolog from example game attached. | ||||||||
Tags | No tags attached. | ||||||||
Checked infolog.txt for Errors | Yes | ||||||||
Attached Files |
|
![]() |
|
esainane (reporter) 2019-11-03 12:07 |
Output from custom sanitized spring attached. Early output truncated due to sanitizers picking up on large numbers of less-than-critical issues; the important output is at the end, immediately as the game started. |
esainane (reporter) 2019-11-03 12:11 |
Core backtrace from unsanitized spring attached. I did not bother loading debugging symbols, since the error was raised from the libc after it detected corrupted internal data, and the important part was that the libc's internal data was corrupted, not the particular instance of new that triggered the check. |
esainane (reporter) 2019-11-03 12:13 |
For completeness, gdb backtrace from pre-modification sanitized spring showing the null pointer dereference, prior to modification to check for the null case. |
Kloot (developer) 2019-11-03 13:42 |
Thanks for debugging this, a sizeof() went MIA here. |
![]() |
|||
Date Modified | Username | Field | Change |
---|---|---|---|
2019-11-03 12:04 | esainane | New Issue | |
2019-11-03 12:04 | esainane | File Added: 20191103070848_infolog.txt | |
2019-11-03 12:07 | esainane | File Added: spring-sanitized-out | |
2019-11-03 12:07 | esainane | Note Added: 0020206 | |
2019-11-03 12:11 | esainane | File Added: spring-core | |
2019-11-03 12:11 | esainane | Note Added: 0020207 | |
2019-11-03 12:13 | esainane | File Added: spring-sanitized-nullpo | |
2019-11-03 12:13 | esainane | Note Added: 0020208 | |
2019-11-03 13:42 | Kloot | Note Added: 0020209 | |
2019-11-03 13:42 | Kloot | Assigned To | => Kloot |
2019-11-03 13:42 | Kloot | Status | new => resolved |
2019-11-03 13:42 | Kloot | Resolution | open => fixed |
2019-11-03 13:42 | Kloot | Fixed in Version | => 104.0 +git |