Skip to content

Commit

Permalink
VFS: Fix handle leak when double-mapping (fixes #1659)
Browse files Browse the repository at this point in the history
  • Loading branch information
endrift committed Feb 8, 2020
1 parent cf456dd commit 5d58944
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -22,6 +22,7 @@ Other fixes:
- 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)
Expand Down
46 changes: 39 additions & 7 deletions src/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
Expand All @@ -14,11 +14,23 @@
#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
};

Expand Down Expand Up @@ -74,12 +86,23 @@ struct VFile* VFileFromFD(int fd) {
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;
}
Expand Down Expand Up @@ -134,16 +157,25 @@ static void* _vfdMap(struct VFile* vf, size_t size, int flags) {
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

Expand Down

0 comments on commit 5d58944

Please sign in to comment.