From: Trent Waddington <trent.waddington@tensorworks.com.au> --- dlls/imagehlp/tests/image.c | 163 ++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/dlls/imagehlp/tests/image.c b/dlls/imagehlp/tests/image.c index 4d7a6f5bdfe..a8bbf85b63d 100644 --- a/dlls/imagehlp/tests/image.c +++ b/dlls/imagehlp/tests/image.c @@ -223,6 +223,110 @@ bin64 = /* final alignment */ {0} }; + +#define FILE_TEXT_2 0x300 +#define NUM_SECTIONS_2 5 +#define FILE_RELOC 0x600 +#define RVA_RELOC 0x4000 +#define FILE_RSRC 0x800 +#define RVA_RSRC 0x5000 +#define FILE_TOTAL_2 0xA00 +#define RVA_TOTAL_2 0x6000 + +static struct image_with_rsrc_and_reloc +{ + IMAGE_DOS_HEADER dos_header; + char __alignment1[FILE_PE_START - sizeof(IMAGE_DOS_HEADER)]; + IMAGE_NT_HEADERS32 nt_headers; + IMAGE_SECTION_HEADER sections[NUM_SECTIONS_2]; + char __alignment2[FILE_TEXT_2 - FILE_PE_START - sizeof(IMAGE_NT_HEADERS32) - + NUM_SECTIONS_2 * sizeof(IMAGE_SECTION_HEADER)]; + unsigned char text_section[FILE_IDATA-FILE_TEXT_2]; + struct imports idata_section; + unsigned char reloc_section[FILE_RSRC-FILE_RELOC]; + unsigned char rsrc_section[FILE_TOTAL_2-FILE_RSRC]; +} +bin_with_rsrc_and_reloc = +{ + /* dos header */ + {IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, 0, {0}, FILE_PE_START}, + /* alignment before PE header */ + {0}, + /* nt headers */ + {IMAGE_NT_SIGNATURE, + /* basic headers - 5 sections, no symbols, EXE file */ + {IMAGE_FILE_MACHINE_I386, NUM_SECTIONS_2, 0, 0, 0, sizeof(IMAGE_OPTIONAL_HEADER32), + IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE}, + /* optional header */ + {IMAGE_NT_OPTIONAL_HDR32_MAGIC, 4, 0, FILE_IDATA-FILE_TEXT_2, + FILE_RELOC-FILE_IDATA + FILE_IDATA-FILE_TEXT_2, 0x400, + RVA_TEXT, RVA_TEXT, RVA_BSS, VA_START, 0x1000, 0x200, 4, 0, 1, 0, 4, 0, 0, + RVA_TOTAL_2, FILE_TEXT_2, 0, IMAGE_SUBSYSTEM_WINDOWS_GUI, 0, + 0x200000, 0x1000, 0x100000, 0x1000, 0, 0x10, + {{0, 0}, + {RVA_IDATA, sizeof(struct imports)} + } + } + }, + /* sections */ + { + {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT_2, FILE_TEXT_2, + 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ}, + {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0, + IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}, + {".idata", {sizeof(struct imports)}, RVA_IDATA, FILE_RELOC-FILE_IDATA, FILE_IDATA, 0, + 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}, + {".reloc", {0x100}, RVA_RELOC, FILE_RSRC-FILE_RELOC, FILE_RELOC, 0, + 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}, + {".rsrc", {0x100}, RVA_RSRC, FILE_TOTAL_2-FILE_RSRC, FILE_RSRC, 0, + 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE} + }, + /* alignment before first section */ + {0}, + /* .text section */ + { + 0x31, 0xC0, /* xor eax, eax */ + 0xFF, 0x25, EXIT_PROCESS&0xFF, (EXIT_PROCESS>>8)&0xFF, (EXIT_PROCESS>>16)&0xFF, + (EXIT_PROCESS>>24)&0xFF, /* jmp ExitProcess */ + 0 + }, + /* .idata section */ + { + { + {{RVA_IDATA + FIELD_OFFSET(struct imports, original_thunks)}, 0, 0, + RVA_IDATA + FIELD_OFFSET(struct imports, dllname), + RVA_IDATA + FIELD_OFFSET(struct imports, thunks) + }, + {{0}, 0, 0, 0, 0} + }, + {{{RVA_IDATA+FIELD_OFFSET(struct imports, ibn)}}, {{0}}}, + {{{RVA_IDATA+FIELD_OFFSET(struct imports, ibn)}}, {{0}}}, + {0,"ExitProcess"}, + "KERNEL32.DLL" + }, + /* .reloc section */ + { + 0 + }, + /* .rsrc section */ + { + 0 + } +}; + +IMAGE_SECTION_HEADER bin_with_rsrc_and_reloc_sections_zeroed[NUM_SECTIONS_2] = +{ + {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT_2, FILE_TEXT_2, + 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ}, + {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0, + IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}, + {".idata", {sizeof(struct imports)}, RVA_IDATA, FILE_RELOC-FILE_IDATA, FILE_IDATA, 0, + 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}, + {".reloc", {0x100}, 0, FILE_RSRC-FILE_RELOC, 0, 0, + 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}, + {".rsrc", {0}, 0, 0, 0, 0, + 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE} +}; #pragma pack(pop) struct blob @@ -358,6 +462,28 @@ static const struct expected_blob b4[] = { }; static const struct expected_update_accum a4 = { ARRAY_SIZE(b4), b4, FALSE }; +static const struct expected_blob b5[] = { + {FILE_PE_START, &bin_with_rsrc_and_reloc}, + /* with zeroed Checksum/SizeOfInitializedData/SizeOfImage fields */ + {sizeof(bin_with_rsrc_and_reloc.nt_headers), &bin_with_rsrc_and_reloc.nt_headers}, + {sizeof(bin_with_rsrc_and_reloc.sections), &bin_with_rsrc_and_reloc_sections_zeroed}, + {FILE_IDATA-FILE_TEXT_2, &bin_with_rsrc_and_reloc.text_section}, + {FILE_RELOC-FILE_IDATA, &bin_with_rsrc_and_reloc.idata_section}, + {FILE_RSRC-FILE_RELOC, &bin_with_rsrc_and_reloc.reloc_section} +}; +static const struct expected_update_accum a5 = { ARRAY_SIZE(b5), b5, FALSE }; + +static const struct expected_blob b6[] = { + {FILE_PE_START, &bin_with_rsrc_and_reloc}, + /* with zeroed Checksum but not SizeOfInitializedData/SizeOfImage fields */ + {sizeof(bin_with_rsrc_and_reloc.nt_headers), &bin_with_rsrc_and_reloc.nt_headers}, + {sizeof(bin_with_rsrc_and_reloc.sections), &bin_with_rsrc_and_reloc.sections}, + {FILE_IDATA-FILE_TEXT_2, &bin_with_rsrc_and_reloc.text_section}, + {FILE_RELOC-FILE_IDATA, &bin_with_rsrc_and_reloc.idata_section}, + {FILE_RSRC-FILE_RELOC, &bin_with_rsrc_and_reloc.reloc_section} +}; +static const struct expected_update_accum a6 = { ARRAY_SIZE(b6), b6, FALSE }; + /* Creates a test file and returns a handle to it. The file's path is returned * in temp_file, which must be at least MAX_PATH characters in length. */ @@ -449,6 +575,7 @@ static void test_get_digest_stream(void) CloseHandle(file); DeleteFileA(temp_file); + /* 64 bit */ file = create_temp_file(temp_file); if (file == INVALID_HANDLE_VALUE) { @@ -478,6 +605,42 @@ static void test_get_digest_stream(void) free_updates(&accum); CloseHandle(file); DeleteFileA(temp_file); + + /* with rsrc and reloc */ + file = create_temp_file(temp_file); + if (file == INVALID_HANDLE_VALUE) + { + skip("couldn't create temp file\n"); + return; + } + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.CheckSum = 0; + checksum = compute_checksum((const WORD *)&bin_with_rsrc_and_reloc, sizeof(bin_with_rsrc_and_reloc)); + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.CheckSum = checksum; + + WriteFile(file, &bin_with_rsrc_and_reloc, sizeof(bin_with_rsrc_and_reloc), &count, NULL); + FlushFileBuffers(file); + + /* zero out some fields ImageGetDigestStream would zero out */ + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.CheckSum = 0; + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.SizeOfInitializedData = 0; + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.SizeOfImage = 0; + + ret = ImageGetDigestStream(file, CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO, + accumulating_stream_output, &accum); + ok(ret, "ImageGetDigestStream failed: %ld\n", GetLastError()); + check_updates("flags = CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO", &a5, &accum); + free_updates(&accum); + + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.SizeOfInitializedData = FILE_RELOC-FILE_IDATA + FILE_IDATA-FILE_TEXT_2; + bin_with_rsrc_and_reloc.nt_headers.OptionalHeader.SizeOfImage = RVA_TOTAL_2; + + ret = ImageGetDigestStream(file, CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO|CERT_PE_IMAGE_DIGEST_RESOURCES, + accumulating_stream_output, &accum); + ok(ret, "ImageGetDigestStream failed: %ld\n", GetLastError()); + check_updates("flags = CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO|CERT_PE_IMAGE_DIGEST_RESOURCES", &a6, &accum); + free_updates(&accum); + CloseHandle(file); + DeleteFileA(temp_file); } static unsigned int got_SysAllocString, got_GetOpenFileNameA, got_SHRegGetIntW; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10295