all repos — mgba @ 5d589441d567a59347cfc51bf3b04d7a464a46b0

mGBA Game Boy Advance Emulator

VFS: Fix handle leak when double-mapping (fixes #1659)
Vicki Pfau vi@endrift.com
Sat, 08 Feb 2020 13:35:15 -0800
commit

5d589441d567a59347cfc51bf3b04d7a464a46b0

parent

cf456dd2a1c68f0f76934c04250e3dbc69cc6b18

2 files changed, 40 insertions(+), 7 deletions(-)

jump to
M CHANGESCHANGES

@@ -22,6 +22,7 @@ - Qt: Fix extraneous dialog (fixes mgba.io/i/1654)

- Qt: Fix window title not updating after shutting down game - Qt: Fix GIF view not allowing manual filename entry - Util: Fix crash reading invalid ELFs + - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: - FFmpeg: Add more presets - Qt: Fix non-SDL build (fixes mgba.io/i/1656)
M src/util/vfs/vfs-fd.csrc/util/vfs/vfs-fd.c

@@ -1,4 +1,4 @@

-/* Copyright (c) 2013-2015 Jeffrey Pfau +/* Copyright (c) 2013-2020 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this

@@ -14,11 +14,23 @@ #else

#include <windows.h> #endif +#include <mgba-util/vector.h> + +#ifdef _WIN32 +struct HandleMappingTuple { + HANDLE handle; + void* mapping; +}; + +DECLARE_VECTOR(HandleMappingList, struct HandleMappingTuple); +DEFINE_VECTOR(HandleMappingList, struct HandleMappingTuple); +#endif + struct VFileFD { struct VFile d; int fd; #ifdef _WIN32 - HANDLE hMap; + struct HandleMappingList handles; #endif };

@@ -74,12 +86,23 @@ vfd->d.unmap = _vfdUnmap;

vfd->d.truncate = _vfdTruncate; vfd->d.size = _vfdSize; vfd->d.sync = _vfdSync; +#ifdef _WIN32 + HandleMappingListInit(&vfd->handles, 4); +#endif return &vfd->d; } bool _vfdClose(struct VFile* vf) { struct VFileFD* vfd = (struct VFileFD*) vf; +#ifdef _WIN32 + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + UnmapViewOfFile(HandleMappingListGetPointer(&vfd->handles, i)->mapping); + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + } + HandleMappingListDeinit(&vfd->handles); +#endif if (close(vfd->fd) < 0) { return false; }

@@ -134,16 +157,25 @@ fileSize = stat.st_size;

if (size > fileSize) { size = fileSize; } - vfd->hMap = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0); - return MapViewOfFile(vfd->hMap, mapFiles, 0, 0, size); + struct HandleMappingTuple tuple = {0}; + tuple.handle = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0); + tuple.mapping = MapViewOfFile(tuple.handle, mapFiles, 0, 0, size); + *HandleMappingListAppend(&vfd->handles) = tuple; + return tuple.mapping; } static void _vfdUnmap(struct VFile* vf, void* memory, size_t size) { UNUSED(size); struct VFileFD* vfd = (struct VFileFD*) vf; - UnmapViewOfFile(memory); - CloseHandle(vfd->hMap); - vfd->hMap = 0; + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + if (HandleMappingListGetPointer(&vfd->handles, i)->mapping == memory) { + UnmapViewOfFile(memory); + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + HandleMappingListShift(&vfd->handles, i, 1); + break; + } + } } #endif