View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002899 | FSSCP | public | 2013-07-05 12:11 | 2014-09-25 02:27 | |
Reporter | Echelon9 | Assigned To | CommanderDJ | ||
Priority | normal | Severity | minor | Reproducibility | have not tried |
Status | resolved | Resolution | fixed | ||
Product Version | 3.7.0 RC2 | ||||
Target Version | 3.7.2 | Fixed in Version | 3.7.2 | ||
Summary | 0002899: AddressSanitizer: heap-buffer-overflow in snd_play() sound.cpp | ||||
Description | Reported by AddressSanitizer, a memory error detector for C/C++, in FS2Open builds based on trunk r9669 + BP.patch for WiH. ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62d0000143f4 at pc 0x1023279b4 bp 0x7fff5fbf5f30 sp 0x7fff5fbf5f28 READ of size 4 at 0x62d0000143f4 thread T0 #0 0x1023279b3 in snd_play sound.cpp:525 0000001 0x10277f9da in l_Audio_playGameSound_f lua.cpp:11013 0000002 0x102afd91f in luaD_precall ldo.c:320 0000003 0x102beb801 in luaV_execute lvm.c:591 0000004 0x102b037dc in luaD_call ldo.c:378 0000005 0x102a92b9e in f_call lapi.c:800 0000006 0x102af78a2 in luaD_rawrunprotected ldo.c:116 0000007 0x102b067cb in luaD_pcall ldo.c:464 0000008 0x102a924f6 in lua_pcall lapi.c:821 0000009 0x10286d0c9 in script_state::RunBytecodeSub scripting.cpp:818 0000010 0x102865401 in script_state::RunBytecode scripting.cpp:859 #11 0x102864f2a in ConditionedHook::Run scripting.cpp:465 0000012 0x10286e1c4 in script_state::RunCondition scripting.cpp:870 0000013 0x10097e6d7 in gr_flip 2d.cpp:1544 0000014 0x1002f2dd7 in game_flip_page_and_time_it freespace.cpp:3992 0000015 0x1002fb9c3 in game_frame freespace.cpp:4616 0000016 0x1002ffa9b in game_do_frame freespace.cpp:4915 0000017 0x10030b5f6 in game_do_state freespace.cpp:6591 0000018 0x100914f68 in gameseq_process_events gamesequence.cpp:405 0000019 0x100311e96 in game_main freespace.cpp:7158 0000020 0x100313534 in SDL_main freespace.cpp:7292 ... 0x62d0000143f4 is located 12 bytes to the left of 36864-byte region [0x62d000014400,0x62d00001d400) allocated by thread T0 here: #0 0x105a588f1 in wrap_malloc _asan_rtl_ 0000001 0x102626948 in _vm_malloc stubs.cpp:571 0000002 0x10092c6aa in SCP_vm_allocator<game_snd>::allocate vmallocator.h:59 0000003 0x10092b5f0 in std::_Vector_base<game_snd, SCP_vm_allocator<game_snd> >::_M_allocate stl_vector.h:131 0000004 0x100929da1 in std::vector<game_snd, SCP_vm_allocator<game_snd> >::_M_insert_aux vector.tcc:271 0000005 0x100926dd2 in std::vector<game_snd, SCP_vm_allocator<game_snd> >::push_back stl_vector.h:608 0000006 0x1009231c5 in parse_sound_table gamesnd.cpp:715 0000007 0x100923e2a in gamesnd_parse_soundstbl gamesnd.cpp:783 0000008 0x1002ce0e4 in game_init freespace.cpp:1927 0000009 0x100311959 in game_main freespace.cpp:7101 0000010 0x100313534 in SDL_main freespace.cpp:7292 int snd_play( game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg ) { ... if (gs == NULL) { Int3(); return -1; } MONITOR_INC( NumSoundsStarted, 1 ); if ( gs->id == -1 ) { <========= gs->id = snd_load(gs); MONITOR_INC( NumSoundsLoaded, 1); } else if ( gs->id_sig != Sounds[gs->id].sig ) { gs->id = snd_load(gs); } | ||||
Steps To Reproduce | 1. Utilise a version of Clang that supports AddressSantizer (https://code.google.com/p/address-sanitizer/wiki/AddressSanitizer). 2. Build with -fsanitize=address C/C++ flag 3. Run the game with mediavps 3.6.12 and BP WiH. Reproducible in mission Everything is Permitted. Get noticed by the guards, being under radar lock warning, and act dead until crash occurs on sufficient weapon hits. | ||||
Additional Information | ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62d0000143f4 at pc 0x1023279b4 bp 0x7fff5fbf5f30 sp 0x7fff5fbf5f28 READ of size 4 at 0x62d0000143f4 thread T0 #0 0x1023279b3 in snd_play sound.cpp:525 0000001 0x10277f9da in l_Audio_playGameSound_f lua.cpp:11013 0000002 0x102afd91f in luaD_precall ldo.c:320 0000003 0x102beb801 in luaV_execute lvm.c:591 0000004 0x102b037dc in luaD_call ldo.c:378 0000005 0x102a92b9e in f_call lapi.c:800 0000006 0x102af78a2 in luaD_rawrunprotected ldo.c:116 0000007 0x102b067cb in luaD_pcall ldo.c:464 0000008 0x102a924f6 in lua_pcall lapi.c:821 0000009 0x10286d0c9 in script_state::RunBytecodeSub scripting.cpp:818 0000010 0x102865401 in script_state::RunBytecode scripting.cpp:859 #11 0x102864f2a in ConditionedHook::Run scripting.cpp:465 0000012 0x10286e1c4 in script_state::RunCondition scripting.cpp:870 0000013 0x10097e6d7 in gr_flip 2d.cpp:1544 0000014 0x1002f2dd7 in game_flip_page_and_time_it freespace.cpp:3992 0000015 0x1002fb9c3 in game_frame freespace.cpp:4616 0000016 0x1002ffa9b in game_do_frame freespace.cpp:4915 0000017 0x10030b5f6 in game_do_state freespace.cpp:6591 0000018 0x100914f68 in gameseq_process_events gamesequence.cpp:405 0000019 0x100311e96 in game_main freespace.cpp:7158 0000020 0x100313534 in SDL_main freespace.cpp:7292 0000021 0x100003203 in -[SDLMain applicationDidFinishLaunching:] SDLMain.m:300 0000022 0x7fff95444ed9 in _CFXNotificationPost (in CoreFoundation) + 2553 0000023 0x7fff8f5c67b5 in -[NSNotificationCenter postNotificationName:object:userInfo:] (in Foundation) + 63 0000024 0x7fff98e5c52c in -[NSApplication _postDidFinishNotification] (in AppKit) + 291 0000025 0x7fff98e5c265 in -[NSApplication _sendFinishLaunchingNotification] (in AppKit) + 215 0000026 0x7fff98e59451 in -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] (in AppKit) + 565 0000027 0x7fff98e5904b in -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] (in AppKit) + 350 0000028 0x7fff8f5e007a in -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] (in Foundation) + 307 0000029 0x7fff8f5dfedc in _NSAppleEventManagerGenericHandler (in Foundation) + 105 0000030 0x7fff94e91077 in aeDispatchAppleEvent(AEDesc const*, AEDesc*, unsigned int, unsigned char*) (in AE) + 306 0000031 0x7fff94e90ed8 in dispatchEventAndSendReply(AEDesc const*, AEDesc*) (in AE) + 36 0000032 0x7fff94e90d98 in aeProcessAppleEvent (in AE) + 317 0000033 0x7fff93c24708 in AEProcessAppleEvent (in HIToolbox) + 99 0000034 0x7fff98e55835 in _DPSNextEvent (in AppKit) + 1455 0000035 0x7fff98e54df1 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] (in AppKit) + 127 0000036 0x7fff98e4c1a2 in -[NSApplication run] (in AppKit) + 516 0000037 0x100005372 in CustomApplicationMain SDLMain.m:227 0000038 0x100004ddf in main SDLMain.m:377 0000039 0x100001f23 in start (in FS2_Open (debug)) + 51 0000040 0x0 in 0x0 0x62d0000143f4 is located 12 bytes to the left of 36864-byte region [0x62d000014400,0x62d00001d400) allocated by thread T0 here: #0 0x105a588f1 in wrap_malloc _asan_rtl_ 0000001 0x102626948 in _vm_malloc stubs.cpp:571 0000002 0x10092c6aa in SCP_vm_allocator<game_snd>::allocate vmallocator.h:59 0000003 0x10092b5f0 in std::_Vector_base<game_snd, SCP_vm_allocator<game_snd> >::_M_allocate stl_vector.h:131 0000004 0x100929da1 in std::vector<game_snd, SCP_vm_allocator<game_snd> >::_M_insert_aux vector.tcc:271 0000005 0x100926dd2 in std::vector<game_snd, SCP_vm_allocator<game_snd> >::push_back stl_vector.h:608 0000006 0x1009231c5 in parse_sound_table gamesnd.cpp:715 0000007 0x100923e2a in gamesnd_parse_soundstbl gamesnd.cpp:783 0000008 0x1002ce0e4 in game_init freespace.cpp:1927 0000009 0x100311959 in game_main freespace.cpp:7101 0000010 0x100313534 in SDL_main freespace.cpp:7292 #11 0x100003203 in -[SDLMain applicationDidFinishLaunching:] SDLMain.m:300 0000012 0x7fff95444ed9 in _CFXNotificationPost (in CoreFoundation) + 2553 0000013 0x7fff8f5c67b5 in -[NSNotificationCenter postNotificationName:object:userInfo:] (in Foundation) + 63 0000014 0x7fff98e5c52c in -[NSApplication _postDidFinishNotification] (in AppKit) + 291 0000015 0x7fff98e5c265 in -[NSApplication _sendFinishLaunchingNotification] (in AppKit) + 215 0000016 0x7fff98e59451 in -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] (in AppKit) + 565 0000017 0x7fff98e5904b in -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] (in AppKit) + 350 0000018 0x7fff8f5e007a in -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] (in Foundation) + 307 0000019 0x7fff8f5dfedc in _NSAppleEventManagerGenericHandler (in Foundation) + 105 0000020 0x7fff94e91077 in aeDispatchAppleEvent(AEDesc const*, AEDesc*, unsigned int, unsigned char*) (in AE) + 306 0000021 0x7fff94e90ed8 in dispatchEventAndSendReply(AEDesc const*, AEDesc*) (in AE) + 36 0000022 0x7fff94e90d98 in aeProcessAppleEvent (in AE) + 317 0000023 0x7fff93c24708 in AEProcessAppleEvent (in HIToolbox) + 99 0000024 0x7fff98e55835 in _DPSNextEvent (in AppKit) + 1455 0000025 0x7fff98e54df1 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] (in AppKit) + 127 0000026 0x7fff98e4c1a2 in -[NSApplication run] (in AppKit) + 516 0000027 0x100005372 in CustomApplicationMain SDLMain.m:227 0000028 0x100004ddf in main SDLMain.m:377 0000029 0x100001f23 in start (in FS2_Open (debug)) + 51 Shadow bytes around the buggy address: 0x1c5a00002820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c5a00002830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c5a00002840: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c5a00002850: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c5a00002860: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x1c5a00002870: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]fa 0x1c5a00002880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x1c5a00002890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x1c5a000028a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x1c5a000028b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x1c5a000028c0: 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 Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 ASan internal: fe ==1923==ABORTING | ||||
Tags | No tags attached. | ||||
|
Resolution patch ready for code review. Was caused by a negative -1 in-band error reporting making its way to be an index into the Snds[] array. |
|
Looks good, although I would recommend to add a LuaError in the else branch as an invalid sound index should be considered a script-error which would be dropped silently otherwise. |
|
fix-mantis-2899-v2.patch (882 bytes)
Index: code/parse/lua.cpp =================================================================== --- code/parse/lua.cpp (revision 9699) +++ code/parse/lua.cpp (working copy) @@ -11010,9 +11010,13 @@ CLAMP(pan, -1.0f, 1.0f); CLAMP(vol, 0.0f, 100.0f); - idx = snd_play(&Snds[gamesnd_get_by_tbl_index(idx)], pan, vol*0.01f, pri, voice_msg); - - return ade_set_args(L, "b", idx > -1); + if (gamesnd_get_by_tbl_index(idx) >= 0) { + idx = snd_play(&Snds[gamesnd_get_by_tbl_index(idx)], pan, vol*0.01f, pri, voice_msg); + return ade_set_args(L, "b", idx > -1); + } else { + LuaError(L, "Invalid sound index %i (Snds[%i]) in playGameSound()", idx, gamesnd_get_by_tbl_index(idx)); + return ADE_RETURN_FALSE; + } } ADE_FUNC(playInterfaceSound, l_Audio, "Sound index", "Plays a sound from #Interface Sounds in sounds.tbl", "boolean", "True if sound was played, false if not") |
|
From IRC #scp: [12:10am] Echelon9: actually, I'm not so sure [12:10am] Echelon9: gamesnd_get_by_tbl_index() seems really odd [12:11am] Echelon9: although it says the lookup is by "tbl_index", it converts the integer to a string and then does a name lookup?!? [12:11am] Echelon9: it in fact looks like a direct numerical index into Snds[] is being passed as first argument to playGameSound [12:12am] Echelon9: which would appear consistent with the function description [12:12am] Echelon9: similar uncertainty between description and implementation applies to gamesnd_get_by_iface_tbl_index() |
|
The problem with gamesnd_get_by_tbl_index() is that it merely exists for legacy support to make the transition from indexed sounds to named sounds easier and to not break existing missions and scripts as the function is only used to look up sounds indexes in these parts of the code. |
|
Yes, but isn't the issue the inconsistency with the Lua API description and a differing internal implementation? The Lua exposed playGameSound() documentation states the argument is a "Sound index" -- to note this appears to be the way WiH has used the Lua API call. The implementation uses the variable as a name lookup I'm not clear how this ever worked? |
|
It worked because it is only there to maintain backwards-compatibility. When the game_snd code was changed to use names instead of ints for sound identifying the numbers were used as names so the present references in other tables would not get invalid and the same was needed for the present scripting functions. The documentation should probably be updated to note that the function is only present for backwards-compatibility and the newer getSoundentry() API should be used for future work. |
|
Thanks for that clarification, makes it much clearer. On that basis though, we should be marking the Lua API documentation for that function with DEPRECATED somehow. Also, while it would be nice to use a LuaError(), a hard error, because it has been used in a number of mods as is, I think it would be inappropriate to adopt now. i.e. WiH would stop working with trunk builds. I think this is an unfortunate case of code deficit we will have to keep. |
|
I didn't realize that this error already happens in released code. Then we will have to use a simple log message along with a modified documentation. |
|
Someone (CommanderDJ perhaps?) is going to need to clarify the reasoning behind the current API. I know there was a discussion about the way to handle integer indexing, but I don't remember the details or reasoning. It does seem counterintuitive to use the integer as the sound index "name" rather than an offset into the sounds array. |
|
This decision was made in order to keep old missions and scripts compatible with the new gamesnd API. A documentation comment noting that these functions should not be used or renaming the functions could also be appropriate but the functionality of these functions must be preserved. |
|
*bump* Has this been fixed in trunk? |
|
Not that I am aware of. |
|
I've been a little out of the loop, and I don't know if I'm really qualified to comment on this. I recall that jg18 was doing a comprehensive review on the sound code - maybe it would be prudent to draw this to his attention? |
|
Most probably best a sound coder reviews, as there is functionality change to fix this properly (I think) |
|
Almost all of the comments on this ticket (including mine) have been about understanding the change from integer-based lookup to name-based lookup. With that resolved, I've examined at the patch, and it looks good. I've also added complementary behavior to playInterfaceSound which appears right below it. |
|
Patch committed. |
Date Modified | Username | Field | Change |
---|---|---|---|
2013-07-05 12:11 | Echelon9 | New Issue | |
2013-07-05 12:25 | Echelon9 | Assigned To | => Echelon9 |
2013-07-05 12:25 | Echelon9 | Status | new => assigned |
2013-07-05 12:26 | Echelon9 | File Added: fix-mantis-2899.patch | |
2013-07-05 12:27 | Echelon9 | Note Added: 0015155 | |
2013-07-05 12:27 | Echelon9 | Status | assigned => code review |
2013-07-05 12:41 | m_m | Note Added: 0015156 | |
2013-07-05 13:09 | Echelon9 | File Deleted: fix-mantis-2899.patch | |
2013-07-05 13:09 | Echelon9 | File Added: fix-mantis-2899-v2.patch | |
2013-07-05 13:10 | Echelon9 | Note Added: 0015157 | |
2013-07-05 13:24 | m_m | Note Added: 0015158 | |
2013-07-06 01:54 | Echelon9 | Note Added: 0015159 | |
2013-07-06 10:35 | m_m | Note Added: 0015160 | |
2013-07-07 03:41 | Echelon9 | Note Added: 0015161 | |
2013-07-07 06:52 | m_m | Note Added: 0015162 | |
2013-08-09 17:20 | Goober5000 | Note Added: 0015216 | |
2013-08-10 09:32 | m_m | Note Added: 0015220 | |
2013-08-14 02:48 | Echelon9 | Assigned To | Echelon9 => CommanderDJ |
2013-08-14 02:48 | Echelon9 | Status | code review => assigned |
2014-03-26 01:32 | Goober5000 | Note Added: 0015682 | |
2014-03-26 11:15 | Echelon9 | Note Added: 0015688 | |
2014-06-09 08:16 | CommanderDJ | Note Added: 0015825 | |
2014-06-29 23:10 | Goober5000 | Target Version | 3.7.0 => 3.7.2 |
2014-08-17 03:07 | Echelon9 | Note Added: 0016225 | |
2014-09-25 02:26 | Goober5000 | Note Added: 0016299 | |
2014-09-25 02:27 | Goober5000 | Changeset attached | => fs2open trunk r11083 |
2014-09-25 02:27 | Goober5000 | Note Added: 0016300 | |
2014-09-25 02:27 | Goober5000 | Status | assigned => resolved |
2014-09-25 02:27 | Goober5000 | Resolution | open => fixed |
2014-09-25 02:27 | Goober5000 | Fixed in Version | => 3.7.2 |