Skip to content

Commit 95de93d

Browse files
authored
Merge pull request #1 from tobias-loew/fix_64_bit_4GB_boundary_problem
fixed 64-bit 4 GB boundary problem
2 parents 5c6b699 + ccfa32a commit 95de93d

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

MemoryModule.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@
5959
typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
6060
typedef int (WINAPI *ExeEntryProc)(void);
6161

62+
#ifdef _WIN64
63+
// simple linked list to store memory blocks that span the 4GB boundary
64+
// (which can't be used as memory for memorymodule)
65+
typedef struct tagPOINTER_LIST{
66+
tagPOINTER_LIST* next;
67+
unsigned char *address;
68+
}POINTER_LIST;
69+
#endif
70+
6271
typedef struct {
6372
PIMAGE_NT_HEADERS headers;
6473
unsigned char *codeBase;
@@ -75,6 +84,9 @@ typedef struct {
7584
void *userdata;
7685
ExeEntryProc exeEntry;
7786
DWORD pageSize;
87+
#ifdef _WIN64
88+
POINTER_LIST* blockedMemory;
89+
#endif
7890
} MEMORYMODULE, *PMEMORYMODULE;
7991

8092
typedef struct {
@@ -125,6 +137,18 @@ OutputLastError(const char *msg)
125137
#endif
126138
}
127139

140+
#ifdef _WIN64
141+
static void FreePointerList(POINTER_LIST* head, CustomFreeFunc freeMemory, void* userdata) {
142+
POINTER_LIST* node = head;
143+
while(node != NULL) {
144+
POINTER_LIST* current = node;
145+
freeMemory(current->address, 0, MEM_RELEASE, userdata);
146+
current = current->next;
147+
free(node);
148+
}
149+
}
150+
#endif
151+
128152
static BOOL
129153
CheckSize(size_t size, size_t expected) {
130154
if (size < expected) {
@@ -523,6 +547,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
523547
size_t optionalSectionSize;
524548
size_t lastSectionEnd = 0;
525549
size_t alignedImageSize;
550+
#ifdef _WIN64
551+
POINTER_LIST* blockedMemory = NULL;
552+
#endif
526553

527554
if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
528555
return NULL;
@@ -598,9 +625,41 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
598625
}
599626
}
600627

628+
#ifdef _WIN64
629+
// check that memory-block does not span over the 4GB border
630+
if ((unsigned long long)(code) / 0x100000000 < (unsigned long long)(code + alignedImageSize) / 0x100000000)
631+
{
632+
POINTER_LIST** current_node_ptr = &blockedMemory;
633+
634+
do
635+
{
636+
// store code to keep bad address blocked
637+
*current_node_ptr = (POINTER_LIST*)malloc(sizeof(POINTER_LIST));
638+
(*current_node_ptr)->next = NULL;
639+
(*current_node_ptr)->address = code;
640+
current_node_ptr = &(*current_node_ptr)->next;
641+
642+
code = (unsigned char *)allocMemory(NULL,
643+
alignedImageSize,
644+
MEM_RESERVE | MEM_COMMIT,
645+
PAGE_READWRITE,
646+
userdata);
647+
648+
if(code == NULL) {
649+
FreePointerList(blockedMemory, freeMemory, userdata);
650+
SetLastError(ERROR_OUTOFMEMORY);
651+
return NULL;
652+
}
653+
} while((unsigned long long)(code) / 0x100000000 < (unsigned long long)(code + alignedImageSize) / 0x100000000);
654+
}
655+
#endif
656+
601657
result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
602658
if (result == NULL) {
603659
freeMemory(code, 0, MEM_RELEASE, userdata);
660+
#ifdef _WIN64
661+
FreePointerList(blockedMemory, freeMemory, userdata);
662+
#endif
604663
SetLastError(ERROR_OUTOFMEMORY);
605664
return NULL;
606665
}
@@ -614,6 +673,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
614673
result->freeLibrary = freeLibrary;
615674
result->userdata = userdata;
616675
result->pageSize = sysInfo.dwPageSize;
676+
#ifdef _WIN64
677+
result->blockedMemory = blockedMemory;
678+
#endif
617679

618680
if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
619681
goto error;
@@ -776,6 +838,11 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
776838
module->free(module->codeBase, 0, MEM_RELEASE, module->userdata);
777839
}
778840

841+
#ifdef _WIN64
842+
// release blockeded memory
843+
FreePointerList(module->blockedMemory, module->free, module->userdata);
844+
#endif
845+
779846
HeapFree(GetProcessHeap(), 0, module);
780847
}
781848

0 commit comments

Comments
 (0)