From f72e74f395ee588161d740c8a891eaafab226b0a Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Sun, 21 Jul 2024 17:12:20 +0300 Subject: [PATCH] [Windows/Linux] Check custom export templates architecture. --- platform/linuxbsd/export/export_plugin.cpp | 100 +++++++++++++++++++-- platform/linuxbsd/export/export_plugin.h | 2 + platform/windows/export/export_plugin.cpp | 64 ++++++++++++- platform/windows/export/export_plugin.h | 2 + 4 files changed, 157 insertions(+), 11 deletions(-) diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp index 936adddda35..0032b898d2a 100644 --- a/platform/linuxbsd/export/export_plugin.cpp +++ b/platform/linuxbsd/export/export_plugin.cpp @@ -61,6 +61,20 @@ Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { + String custom_debug = p_preset->get("custom_template/debug"); + String custom_release = p_preset->get("custom_template/release"); + String arch = p_preset->get("binary_format/architecture"); + + String template_path = p_debug ? custom_debug : custom_release; + template_path = template_path.strip_edges(); + if (!template_path.is_empty()) { + String exe_arch = _get_exe_arch(template_path); + if (arch != exe_arch) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture, found \"%s\", expected \"%s\"."), exe_arch, arch)); + return ERR_CANT_CREATE; + } + } + bool export_as_zip = p_path.ends_with("zip"); String pkg_name; @@ -205,8 +219,76 @@ bool EditorExportPlatformLinuxBSD::is_executable(const String &p_path) const { return is_elf(p_path) || is_shebang(p_path); } +bool EditorExportPlatformLinuxBSD::has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const { + String err; + bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug); + + String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges(); + String custom_release = p_preset->get("custom_template/release").operator String().strip_edges(); + String arch = p_preset->get("binary_format/architecture"); + + if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) { + String exe_arch = _get_exe_arch(custom_debug); + if (arch != exe_arch) { + err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n"; + } + } + if (!custom_release.is_empty() && FileAccess::exists(custom_release)) { + String exe_arch = _get_exe_arch(custom_release); + if (arch != exe_arch) { + err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n"; + } + } + + if (!err.is_empty()) { + r_error = err; + } + + return valid; +} + +String EditorExportPlatformLinuxBSD::_get_exe_arch(const String &p_path) const { + Ref f = FileAccess::open(p_path, FileAccess::READ); + if (f.is_null()) { + return "invalid"; + } + + // Read and check ELF magic number. + { + uint32_t magic = f->get_32(); + if (magic != 0x464c457f) { // 0x7F + "ELF" + return "invalid"; + } + } + + // Process header. + int64_t header_pos = f->get_position(); + f->seek(header_pos + 14); + uint16_t machine = f->get_16(); + f->close(); + + switch (machine) { + case 0x0003: + return "x86_32"; + case 0x003e: + return "x86_64"; + case 0x0014: + return "ppc32"; + case 0x0015: + return "ppc64"; + case 0x0028: + return "arm32"; + case 0x00b7: + return "arm64"; + case 0x00f3: + return "rv64"; + default: + return "unknown"; + } +} + Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { - // Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data + // Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data. Ref f = FileAccess::open(p_path, FileAccess::READ_WRITE); if (f.is_null()) { @@ -214,7 +296,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int return ERR_CANT_OPEN; } - // Read and check ELF magic number + // Read and check ELF magic number. { uint32_t magic = f->get_32(); if (magic != 0x464c457f) { // 0x7F + "ELF" @@ -223,7 +305,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int } } - // Read program architecture bits from class field + // Read program architecture bits from class field. int bits = f->get_8() * 32; @@ -231,7 +313,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("32-bit executables cannot have embedded data >= 4 GiB.")); } - // Get info about the section header table + // Get info about the section header table. int64_t section_table_pos; int64_t section_header_size; @@ -249,13 +331,13 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int int num_sections = f->get_16(); int string_section_idx = f->get_16(); - // Load the strings table + // Load the strings table. uint8_t *strings; { - // Jump to the strings section header + // Jump to the strings section header. f->seek(section_table_pos + string_section_idx * section_header_size); - // Read strings data size and offset + // Read strings data size and offset. int64_t string_data_pos; int64_t string_data_size; if (bits == 32) { @@ -268,7 +350,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int string_data_size = f->get_64(); } - // Read strings data + // Read strings data. f->seek(string_data_pos); strings = (uint8_t *)memalloc(string_data_size); if (!strings) { @@ -277,7 +359,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int f->get_buffer(strings, string_data_size); } - // Search for the "pck" section + // Search for the "pck" section. bool found = false; for (int i = 0; i < num_sections; ++i) { diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h index 21bd81ed2f9..bbc55b82ce0 100644 --- a/platform/linuxbsd/export/export_plugin.h +++ b/platform/linuxbsd/export/export_plugin.h @@ -69,11 +69,13 @@ class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { bool is_shebang(const String &p_path) const; Error _export_debug_script(const Ref &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); + String _get_exe_arch(const String &p_path) const; public: virtual void get_export_options(List *r_options) const override; virtual List get_binary_extensions(const Ref &p_preset) const override; virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override; + virtual bool has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override; virtual Error export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 12694b0155d..b465bd4ecd7 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -187,6 +187,12 @@ Error EditorExportPlatformWindows::export_project(const Ref template_path = template_path.strip_edges(); if (template_path.is_empty()) { template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", arch)); + } else { + String exe_arch = _get_exe_arch(template_path); + if (arch != exe_arch) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch)); + return ERR_CANT_CREATE; + } } int export_angle = p_preset->get("application/export_angle"); @@ -753,9 +759,26 @@ Error EditorExportPlatformWindows::_code_sign(const Ref &p_p } bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const { - String err = ""; + String err; bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug); + String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges(); + String custom_release = p_preset->get("custom_template/release").operator String().strip_edges(); + String arch = p_preset->get("binary_format/architecture"); + + if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) { + String exe_arch = _get_exe_arch(custom_debug); + if (arch != exe_arch) { + err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n"; + } + } + if (!custom_release.is_empty() && FileAccess::exists(custom_release)) { + String exe_arch = _get_exe_arch(custom_release); + if (arch != exe_arch) { + err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n"; + } + } + String rcedit_path = EDITOR_GET("export/windows/rcedit"); if (p_preset->get("application/modify_resources") && rcedit_path.is_empty()) { err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > rcedit) to change the icon or app information data.") + "\n"; @@ -769,7 +792,7 @@ bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref &p_preset, String &r_error) const { - String err = ""; + String err; bool valid = true; List options; @@ -793,6 +816,43 @@ bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref f = FileAccess::open(p_path, FileAccess::READ); + if (f.is_null()) { + return "invalid"; + } + + // Jump to the PE header and check the magic number. + { + f->seek(0x3c); + uint32_t pe_pos = f->get_32(); + + f->seek(pe_pos); + uint32_t magic = f->get_32(); + if (magic != 0x00004550) { + return "invalid"; + } + } + + // Process header. + uint16_t machine = f->get_16(); + f->close(); + + switch (machine) { + case 0x014c: + return "x86_32"; + case 0x8664: + return "x86_64"; + case 0x01c0: + case 0x01c4: + return "arm32"; + case 0xaa64: + return "arm64"; + default: + return "unknown"; + } +} + Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index c644b1f9e1a..6ccb4a15a74 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -73,6 +73,8 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC { Error _rcedit_add_data(const Ref &p_preset, const String &p_path, bool p_console_icon); Error _code_sign(const Ref &p_preset, const String &p_path); + String _get_exe_arch(const String &p_path) const; + public: virtual Error export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; virtual Error modify_template(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) override;