all repos — mgba @ baeb3536942f7ee9ab6cd8b119f03c30ba9d17be

mGBA Game Boy Advance Emulator

VFS: Fix handle leak when double-mapping (fixes #1659)
Vicki Pfau vi@endrift.com
Wed, 05 Feb 2020 04:15:43 +0000
commit

baeb3536942f7ee9ab6cd8b119f03c30ba9d17be

parent

6b12eddfba654300833e3806d83011d978480f2c

2 files changed, 39 insertions(+), 6 deletions(-)

jump to
M CHANGESCHANGES

@@ -31,6 +31,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: Renderer can be changed while a game is running
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; + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + if (HandleMappingListGetPointer(&vfd->handles, i)->mapping == memory) { + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + HandleMappingListShift(&vfd->handles, i, 1); + break; + } + } UnmapViewOfFile(memory); - CloseHandle(vfd->hMap); - vfd->hMap = 0; } #endif