@@ -68,6 +68,7 @@ typedef struct {
6868
6969#define GET_HEADER_DICTIONARY (module , idx ) &(module)->headers->OptionalHeader.DataDirectory[idx]
7070#define ALIGN_DOWN (address , alignment ) (LPVOID)((uintptr_t)(address) & ~((alignment) - 1))
71+ #define ALIGN_VALUE_UP (value , alignment ) (((value) + (alignment) - 1) & ~((alignment) - 1))
7172
7273#ifdef DEBUG_OUTPUT
7374static void
@@ -86,20 +87,30 @@ OutputLastError(const char *msg)
8687#endif
8788
8889static BOOL
89- CopySections (const unsigned char * data , PIMAGE_NT_HEADERS old_headers , PMEMORYMODULE module )
90+ CheckSize (size_t size , size_t expected ) {
91+ if (size < expected ) {
92+ SetLastError (ERROR_INVALID_DATA );
93+ return FALSE;
94+ }
95+
96+ return TRUE;
97+ }
98+
99+ static BOOL
100+ CopySections (const unsigned char * data , size_t size , PIMAGE_NT_HEADERS old_headers , PMEMORYMODULE module )
90101{
91- int i , size ;
102+ int i , section_size ;
92103 unsigned char * codeBase = module -> codeBase ;
93104 unsigned char * dest ;
94105 PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION (module -> headers );
95106 for (i = 0 ; i < module -> headers -> FileHeader .NumberOfSections ; i ++ , section ++ ) {
96107 if (section -> SizeOfRawData == 0 ) {
97108 // section doesn't contain data in the dll itself, but may define
98109 // uninitialized data
99- size = old_headers -> OptionalHeader .SectionAlignment ;
100- if (size > 0 ) {
110+ section_size = old_headers -> OptionalHeader .SectionAlignment ;
111+ if (section_size > 0 ) {
101112 dest = (unsigned char * )VirtualAlloc (codeBase + section -> VirtualAddress ,
102- size ,
113+ section_size ,
103114 MEM_COMMIT ,
104115 PAGE_READWRITE );
105116 if (dest == NULL ) {
@@ -110,13 +121,17 @@ CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMO
110121 // than page size.
111122 dest = codeBase + section -> VirtualAddress ;
112123 section -> Misc .PhysicalAddress = (DWORD ) (uintptr_t ) dest ;
113- memset (dest , 0 , size );
124+ memset (dest , 0 , section_size );
114125 }
115126
116127 // section is empty
117128 continue ;
118129 }
119130
131+ if (!CheckSize (size , section -> PointerToRawData + section -> SizeOfRawData )) {
132+ return FALSE;
133+ }
134+
120135 // commit memory block and copy data from dll
121136 dest = (unsigned char * )VirtualAlloc (codeBase + section -> VirtualAddress ,
122137 section -> SizeOfRawData ,
@@ -285,7 +300,7 @@ ExecuteTLS(PMEMORYMODULE module)
285300}
286301
287302static BOOL
288- PerformBaseRelocation (PMEMORYMODULE module , SIZE_T delta )
303+ PerformBaseRelocation (PMEMORYMODULE module , ptrdiff_t delta )
289304{
290305 unsigned char * codeBase = module -> codeBase ;
291306 PIMAGE_BASE_RELOCATION relocation ;
@@ -428,30 +443,43 @@ static void _FreeLibrary(HCUSTOMMODULE module, void *userdata)
428443 FreeLibrary ((HMODULE ) module );
429444}
430445
431- HMEMORYMODULE MemoryLoadLibrary (const void * data )
446+ HMEMORYMODULE MemoryLoadLibrary (const void * data , size_t size )
432447{
433- return MemoryLoadLibraryEx (data , _LoadLibrary , _GetProcAddress , _FreeLibrary , NULL );
448+ return MemoryLoadLibraryEx (data , size , _LoadLibrary , _GetProcAddress , _FreeLibrary , NULL );
434449}
435450
436- HMEMORYMODULE MemoryLoadLibraryEx (const void * data ,
451+ #include <stdio.h>
452+
453+ HMEMORYMODULE MemoryLoadLibraryEx (const void * data , size_t size ,
437454 CustomLoadLibraryFunc loadLibrary ,
438455 CustomGetProcAddressFunc getProcAddress ,
439456 CustomFreeLibraryFunc freeLibrary ,
440457 void * userdata )
441458{
442- PMEMORYMODULE result ;
459+ PMEMORYMODULE result = NULL ;
443460 PIMAGE_DOS_HEADER dos_header ;
444461 PIMAGE_NT_HEADERS old_header ;
445462 unsigned char * code , * headers ;
446- SIZE_T locationDelta ;
463+ ptrdiff_t locationDelta ;
447464 SYSTEM_INFO sysInfo ;
465+ PIMAGE_SECTION_HEADER section ;
466+ DWORD i ;
467+ size_t optionalSectionSize ;
468+ size_t lastSectionEnd = 0 ;
469+ size_t alignedImageSize ;
448470
471+ if (!CheckSize (size , sizeof (IMAGE_DOS_HEADER ))) {
472+ return NULL ;
473+ }
449474 dos_header = (PIMAGE_DOS_HEADER )data ;
450475 if (dos_header -> e_magic != IMAGE_DOS_SIGNATURE ) {
451476 SetLastError (ERROR_BAD_EXE_FORMAT );
452477 return NULL ;
453478 }
454479
480+ if (!CheckSize (size , dos_header -> e_lfanew + sizeof (IMAGE_NT_HEADERS ))) {
481+ return NULL ;
482+ }
455483 old_header = (PIMAGE_NT_HEADERS )& ((const unsigned char * )(data ))[dos_header -> e_lfanew ];
456484 if (old_header -> Signature != IMAGE_NT_SIGNATURE ) {
457485 SetLastError (ERROR_BAD_EXE_FORMAT );
@@ -473,18 +501,41 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
473501 return NULL ;
474502 }
475503
504+ section = IMAGE_FIRST_SECTION (old_header );
505+ optionalSectionSize = old_header -> OptionalHeader .SectionAlignment ;
506+ for (i = 0 ; i < old_header -> FileHeader .NumberOfSections ; i ++ , section ++ ) {
507+ size_t endOfSection ;
508+ if (section -> SizeOfRawData == 0 ) {
509+ // Section without data in the DLL
510+ endOfSection = section -> VirtualAddress + optionalSectionSize ;
511+ } else {
512+ endOfSection = section -> VirtualAddress + section -> SizeOfRawData ;
513+ }
514+
515+ if (endOfSection > lastSectionEnd ) {
516+ lastSectionEnd = endOfSection ;
517+ }
518+ }
519+
520+ GetNativeSystemInfo (& sysInfo );
521+ alignedImageSize = ALIGN_VALUE_UP (old_header -> OptionalHeader .SizeOfImage , sysInfo .dwPageSize );
522+ if (alignedImageSize != ALIGN_VALUE_UP (lastSectionEnd , sysInfo .dwPageSize )) {
523+ SetLastError (ERROR_BAD_EXE_FORMAT );
524+ return NULL ;
525+ }
526+
476527 // reserve memory for image of library
477528 // XXX: is it correct to commit the complete memory region at once?
478529 // calling DllEntry raises an exception if we don't...
479530 code = (unsigned char * )VirtualAlloc ((LPVOID )(old_header -> OptionalHeader .ImageBase ),
480- old_header -> OptionalHeader . SizeOfImage ,
531+ alignedImageSize ,
481532 MEM_RESERVE | MEM_COMMIT ,
482533 PAGE_READWRITE );
483534
484535 if (code == NULL ) {
485536 // try to allocate memory at arbitrary position
486537 code = (unsigned char * )VirtualAlloc (NULL ,
487- old_header -> OptionalHeader . SizeOfImage ,
538+ alignedImageSize ,
488539 MEM_RESERVE | MEM_COMMIT ,
489540 PAGE_READWRITE );
490541 if (code == NULL ) {
@@ -506,10 +557,12 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
506557 result -> getProcAddress = getProcAddress ;
507558 result -> freeLibrary = freeLibrary ;
508559 result -> userdata = userdata ;
509-
510- GetNativeSystemInfo (& sysInfo );
511560 result -> pageSize = sysInfo .dwPageSize ;
512561
562+ if (!CheckSize (size , old_header -> OptionalHeader .SizeOfHeaders )) {
563+ goto error ;
564+ }
565+
513566 // commit memory for headers
514567 headers = (unsigned char * )VirtualAlloc (code ,
515568 old_header -> OptionalHeader .SizeOfHeaders ,
@@ -524,12 +577,12 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
524577 result -> headers -> OptionalHeader .ImageBase = (uintptr_t )code ;
525578
526579 // copy sections from DLL file block to new memory location
527- if (!CopySections ((const unsigned char * ) data , old_header , result )) {
580+ if (!CopySections ((const unsigned char * ) data , size , old_header , result )) {
528581 goto error ;
529582 }
530583
531584 // adjust base address of imported data
532- locationDelta = (SIZE_T )( code - old_header -> OptionalHeader .ImageBase );
585+ locationDelta = (ptrdiff_t )( result -> headers -> OptionalHeader . ImageBase - old_header -> OptionalHeader .ImageBase );
533586 if (locationDelta != 0 ) {
534587 result -> isRelocated = PerformBaseRelocation (result , locationDelta );
535588 } else {
0 commit comments