mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
client/CVideoHandler.cpp: fix crash on video playback
Avoid buffer overflow caused by sws_scale(): http://trac.ffmpeg.org/ticket/9254 Currently (ffmpeg-4.4 with SSE3 enabled) sws_scale() has a few requirements for target data buffers on rescaling: 1. buffer has to be aligned to be usable for SIMD instructions 2. buffer has to be padded to allow small overflow by SIMD instructions Unfortunately SDL_Surface does not provide these guarantees. This means that atempt to rescale directly into SDL surface causes memory corruption. Usually it happens on campaign selection screen where short video moves start spinning on mouse hover. To fix [1.] we use av_malloc() for memory allocation. To fix [2.] we add an `ffmpeg_pad` that provides plenty of space. We have to use intermdiate buffer and then use memcpy() to land it to SDL_Surface. Without the change crash has the following backtrace: ``` (gdb) bt (c=0x47508940, src=0x1ffeffef50, srcStride=0x1ffeffef30, srcSliceY=0, srcSliceH=116, dst=0x1ffeffef70, dstStride=0x1ffeffef40) at src/libswscale/x86/yuv2rgb_template.c:119 (c=<optimized out>, srcSlice=<optimized out>, srcStride=0x432afa20, srcSliceY=<optimized out>, srcSliceH=116, dst=<optimized out>, dstStride=0x1ffefff0a0) at src/libswscale/swscale.c:969 (this=0x1abaa330, x=90, y=72, dst=0x1a85a4c0, forceRedraw=<optimized out>, update=<optimized out>) at ../vcmi-9999/client/CVideoHandler.cpp:332 at ../vcmi-9999/client/gui/CIntObject.cpp:83 at ../vcmi-9999/client/gui/CGuiHandler.cpp:462 ``` valgrind points to corruption right in sws_scale(): ``` Invalid write of size 8 at 0x6C50BD3: ??? (in /usr/lib64/libswscale.so.5.7.100) by 0x6C4FAE6: yuv420_rgb32_ssse3 (yuv2rgb_template.c:119) by 0x6C28DF2: sws_scale (swscale.c:969) by 0x4566F6: CVideoPlayer::nextFrame() (CVideoHandler.cpp:293) by 0x4573A6: CVideoPlayer::update(int, int, SDL_Surface*, bool, bool) (CVideoHandler.cpp:332) by 0x25EC94: CIntObject::show(SDL_Surface*) [clone .part.0] (CIntObject.cpp:83) by 0x34E855: CMainMenu::update() (CMainMenu.cpp:319) by 0x25D589: CGuiHandler::renderFrame() (CGuiHandler.cpp:462) by 0x1F7450: mainLoop (CMT.cpp:1387) by 0x1F7450: main (CMT.cpp:513) Address 0x475088a8 is 0 bytes after a block of size 92,840 alloc'd at 0x483F7E5: malloc (vg_replace_malloc.c:380) by 0x52B4E23: SDL_malloc_REAL (SDL_malloc.c:5387) by 0x5266237: SDL_SIMDAlloc_REAL (SDL_cpuinfo.c:963) by 0x52EF042: SDL_CreateRGBSurfaceWithFormat_REAL (SDL_surface.c:123) by 0x2649AC: CSDL_Ext::newSurface(int, int, SDL_Surface*) (SDL_Extensions.cpp:42) by 0x457B20: CVideoPlayer::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool) (CVideoHandler.cpp:182) by 0x457C60: CVideoPlayer::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool) (CVideoHandler.cpp:84) by 0x35B14E: CCampaignScreen::CCampaignButton::show(SDL_Surface*) (CCampaignScreen.cpp:126) by 0x25EC94: CIntObject::show(SDL_Surface*) [clone .part.0] (CIntObject.cpp:83) by 0x34E855: CMainMenu::update() (CMainMenu.cpp:319) by 0x25D589: CGuiHandler::renderFrame() (CGuiHandler.cpp:462) by 0x1F7450: mainLoop (CMT.cpp:1387) by 0x1F7450: main (CMT.cpp:513) ``` Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
This commit is contained in:
parent
b1db6e26d1
commit
23215e039c
@ -287,11 +287,32 @@ bool CVideoPlayer::nextFrame()
|
||||
}
|
||||
else
|
||||
{
|
||||
pict.data[0] = (ui8 *)dest->pixels;
|
||||
/* Avoid buffer overflow caused by sws_scale():
|
||||
* http://trac.ffmpeg.org/ticket/9254
|
||||
* Currently (ffmpeg-4.4 with SSE3 enabled) sws_scale()
|
||||
* has a few requirements for target data buffers on rescaling:
|
||||
* 1. buffer has to be aligned to be usable for SIMD instructions
|
||||
* 2. buffer has to be padded to allow small overflow by SIMD instructions
|
||||
* Unfortunately SDL_Surface does not provide these guarantees.
|
||||
* This means that atempt to rescale directly into SDL surface causes
|
||||
* memory corruption. Usually it happens on campaign selection screen
|
||||
* where short video moves start spinning on mouse hover.
|
||||
*
|
||||
* To fix [1.] we use av_malloc() for memory allocation.
|
||||
* To fix [2.] we add an `ffmpeg_pad` that provides plenty of space.
|
||||
* We have to use intermdiate buffer and then use memcpy() to land it
|
||||
* to SDL_Surface.
|
||||
*/
|
||||
size_t pic_bytes = dest->pitch * dest->h;
|
||||
size_t ffmped_pad = 1024; /* a few bytes of overflow will go here */
|
||||
void * for_sws = av_malloc (pic_bytes + ffmped_pad);
|
||||
pict.data[0] = (ui8 *)for_sws;
|
||||
pict.linesize[0] = dest->pitch;
|
||||
|
||||
sws_scale(sws, frame->data, frame->linesize,
|
||||
0, codecContext->height, pict.data, pict.linesize);
|
||||
memcpy(dest->pixels, for_sws, pic_bytes);
|
||||
av_free(for_sws);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user