Skip to content

Commit 9e29595

Browse files
committed
Prevent memory of library from spanning over 4GB bounaries.
Based on code from #67 / #79, fixes #63.
1 parent 55577d9 commit 9e29595

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

MemoryModule.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ struct ExportNameEntry {
7070
typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
7171
typedef int (WINAPI *ExeEntryProc)(void);
7272

73+
#ifdef _WIN64
74+
typedef struct POINTER_LIST {
75+
struct POINTER_LIST *next;
76+
void *address;
77+
} POINTER_LIST;
78+
#endif
79+
7380
typedef struct {
7481
PIMAGE_NT_HEADERS headers;
7582
unsigned char *codeBase;
@@ -87,6 +94,9 @@ typedef struct {
8794
void *userdata;
8895
ExeEntryProc exeEntry;
8996
DWORD pageSize;
97+
#ifdef _WIN64
98+
POINTER_LIST *blockedMemory;
99+
#endif
90100
} MEMORYMODULE, *PMEMORYMODULE;
91101

92102
typedef struct {
@@ -137,6 +147,21 @@ OutputLastError(const char *msg)
137147
#endif
138148
}
139149

150+
#ifdef _WIN64
151+
static void
152+
FreePointerList(POINTER_LIST *head, CustomFreeFunc freeMemory, void *userdata)
153+
{
154+
POINTER_LIST *node = head;
155+
while (node) {
156+
POINTER_LIST *next;
157+
freeMemory(node->address, 0, MEM_RELEASE, userdata);
158+
next = node->next;
159+
free(node);
160+
node = next;
161+
}
162+
}
163+
#endif
164+
140165
static BOOL
141166
CheckSize(size_t size, size_t expected) {
142167
if (size < expected) {
@@ -535,6 +560,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
535560
size_t optionalSectionSize;
536561
size_t lastSectionEnd = 0;
537562
size_t alignedImageSize;
563+
#ifdef _WIN64
564+
POINTER_LIST *blockedMemory = NULL;
565+
#endif
538566

539567
if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
540568
return NULL;
@@ -610,9 +638,40 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
610638
}
611639
}
612640

641+
#ifdef _WIN64
642+
// Memory block may not span 4 GB boundaries.
643+
while ((((uintptr_t) code) >> 32) < (((uintptr_t) (code + alignedImageSize)) >> 32)) {
644+
POINTER_LIST *node = (POINTER_LIST*) malloc(sizeof(POINTER_LIST));
645+
if (!node) {
646+
freeMemory(code, 0, MEM_RELEASE, userdata);
647+
FreePointerList(blockedMemory, freeMemory, userdata);
648+
SetLastError(ERROR_OUTOFMEMORY);
649+
return NULL;
650+
}
651+
652+
node->next = blockedMemory;
653+
node->address = code;
654+
blockedMemory = node;
655+
656+
code = (unsigned char *)allocMemory(NULL,
657+
alignedImageSize,
658+
MEM_RESERVE | MEM_COMMIT,
659+
PAGE_READWRITE,
660+
userdata);
661+
if (code == NULL) {
662+
FreePointerList(blockedMemory, freeMemory, userdata);
663+
SetLastError(ERROR_OUTOFMEMORY);
664+
return NULL;
665+
}
666+
}
667+
#endif
668+
613669
result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
614670
if (result == NULL) {
615671
freeMemory(code, 0, MEM_RELEASE, userdata);
672+
#ifdef _WIN64
673+
FreePointerList(blockedMemory, freeMemory, userdata);
674+
#endif
616675
SetLastError(ERROR_OUTOFMEMORY);
617676
return NULL;
618677
}
@@ -626,6 +685,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
626685
result->freeLibrary = freeLibrary;
627686
result->userdata = userdata;
628687
result->pageSize = sysInfo.dwPageSize;
688+
#ifdef _WIN64
689+
result->blockedMemory = blockedMemory;
690+
#endif
629691

630692
if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
631693
goto error;
@@ -823,6 +885,9 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
823885
module->free(module->codeBase, 0, MEM_RELEASE, module->userdata);
824886
}
825887

888+
#ifdef _WIN64
889+
FreePointerList(module->blockedMemory, module->free, module->userdata);
890+
#endif
826891
HeapFree(GetProcessHeap(), 0, module);
827892
}
828893

0 commit comments

Comments
 (0)