Skip to content

Commit 48f2442

Browse files
committedAug 16, 2024
Merge pull request #94588 from bruvzg/check_custom_templ_arch
[Windows/Linux] Check custom export templates architecture.
2 parents 759d7d4 + f72e74f commit 48f2442

File tree

4 files changed

+157
-11
lines changed

4 files changed

+157
-11
lines changed
 

‎platform/linuxbsd/export/export_plugin.cpp

+91-9
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportP
6161
}
6262

6363
Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
64+
String custom_debug = p_preset->get("custom_template/debug");
65+
String custom_release = p_preset->get("custom_template/release");
66+
String arch = p_preset->get("binary_format/architecture");
67+
68+
String template_path = p_debug ? custom_debug : custom_release;
69+
template_path = template_path.strip_edges();
70+
if (!template_path.is_empty()) {
71+
String exe_arch = _get_exe_arch(template_path);
72+
if (arch != exe_arch) {
73+
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture, found \"%s\", expected \"%s\"."), exe_arch, arch));
74+
return ERR_CANT_CREATE;
75+
}
76+
}
77+
6478
bool export_as_zip = p_path.ends_with("zip");
6579

6680
String pkg_name;
@@ -205,16 +219,84 @@ bool EditorExportPlatformLinuxBSD::is_executable(const String &p_path) const {
205219
return is_elf(p_path) || is_shebang(p_path);
206220
}
207221

222+
bool EditorExportPlatformLinuxBSD::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
223+
String err;
224+
bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug);
225+
226+
String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges();
227+
String custom_release = p_preset->get("custom_template/release").operator String().strip_edges();
228+
String arch = p_preset->get("binary_format/architecture");
229+
230+
if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) {
231+
String exe_arch = _get_exe_arch(custom_debug);
232+
if (arch != exe_arch) {
233+
err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
234+
}
235+
}
236+
if (!custom_release.is_empty() && FileAccess::exists(custom_release)) {
237+
String exe_arch = _get_exe_arch(custom_release);
238+
if (arch != exe_arch) {
239+
err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
240+
}
241+
}
242+
243+
if (!err.is_empty()) {
244+
r_error = err;
245+
}
246+
247+
return valid;
248+
}
249+
250+
String EditorExportPlatformLinuxBSD::_get_exe_arch(const String &p_path) const {
251+
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
252+
if (f.is_null()) {
253+
return "invalid";
254+
}
255+
256+
// Read and check ELF magic number.
257+
{
258+
uint32_t magic = f->get_32();
259+
if (magic != 0x464c457f) { // 0x7F + "ELF"
260+
return "invalid";
261+
}
262+
}
263+
264+
// Process header.
265+
int64_t header_pos = f->get_position();
266+
f->seek(header_pos + 14);
267+
uint16_t machine = f->get_16();
268+
f->close();
269+
270+
switch (machine) {
271+
case 0x0003:
272+
return "x86_32";
273+
case 0x003e:
274+
return "x86_64";
275+
case 0x0014:
276+
return "ppc32";
277+
case 0x0015:
278+
return "ppc64";
279+
case 0x0028:
280+
return "arm32";
281+
case 0x00b7:
282+
return "arm64";
283+
case 0x00f3:
284+
return "rv64";
285+
default:
286+
return "unknown";
287+
}
288+
}
289+
208290
Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
209-
// Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data
291+
// Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data.
210292

211293
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE);
212294
if (f.is_null()) {
213295
add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), vformat(TTR("Failed to open executable file \"%s\"."), p_path));
214296
return ERR_CANT_OPEN;
215297
}
216298

217-
// Read and check ELF magic number
299+
// Read and check ELF magic number.
218300
{
219301
uint32_t magic = f->get_32();
220302
if (magic != 0x464c457f) { // 0x7F + "ELF"
@@ -223,15 +305,15 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
223305
}
224306
}
225307

226-
// Read program architecture bits from class field
308+
// Read program architecture bits from class field.
227309

228310
int bits = f->get_8() * 32;
229311

230312
if (bits == 32 && p_embedded_size >= 0x100000000) {
231313
add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("32-bit executables cannot have embedded data >= 4 GiB."));
232314
}
233315

234-
// Get info about the section header table
316+
// Get info about the section header table.
235317

236318
int64_t section_table_pos;
237319
int64_t section_header_size;
@@ -249,13 +331,13 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
249331
int num_sections = f->get_16();
250332
int string_section_idx = f->get_16();
251333

252-
// Load the strings table
334+
// Load the strings table.
253335
uint8_t *strings;
254336
{
255-
// Jump to the strings section header
337+
// Jump to the strings section header.
256338
f->seek(section_table_pos + string_section_idx * section_header_size);
257339

258-
// Read strings data size and offset
340+
// Read strings data size and offset.
259341
int64_t string_data_pos;
260342
int64_t string_data_size;
261343
if (bits == 32) {
@@ -268,7 +350,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
268350
string_data_size = f->get_64();
269351
}
270352

271-
// Read strings data
353+
// Read strings data.
272354
f->seek(string_data_pos);
273355
strings = (uint8_t *)memalloc(string_data_size);
274356
if (!strings) {
@@ -277,7 +359,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
277359
f->get_buffer(strings, string_data_size);
278360
}
279361

280-
// Search for the "pck" section
362+
// Search for the "pck" section.
281363

282364
bool found = false;
283365
for (int i = 0; i < num_sections; ++i) {

‎platform/linuxbsd/export/export_plugin.h

+2
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC {
6969
bool is_shebang(const String &p_path) const;
7070

7171
Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path);
72+
String _get_exe_arch(const String &p_path) const;
7273

7374
public:
7475
virtual void get_export_options(List<ExportOption> *r_options) const override;
7576
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
7677
virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override;
78+
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
7779
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
7880
virtual String get_template_file_name(const String &p_target, const String &p_arch) const override;
7981
virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override;

‎platform/windows/export/export_plugin.cpp

+62-2
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
187187
template_path = template_path.strip_edges();
188188
if (template_path.is_empty()) {
189189
template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", arch));
190+
} else {
191+
String exe_arch = _get_exe_arch(template_path);
192+
if (arch != exe_arch) {
193+
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch));
194+
return ERR_CANT_CREATE;
195+
}
190196
}
191197

192198
int export_angle = p_preset->get("application/export_angle");
@@ -753,9 +759,26 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
753759
}
754760

755761
bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
756-
String err = "";
762+
String err;
757763
bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug);
758764

765+
String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges();
766+
String custom_release = p_preset->get("custom_template/release").operator String().strip_edges();
767+
String arch = p_preset->get("binary_format/architecture");
768+
769+
if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) {
770+
String exe_arch = _get_exe_arch(custom_debug);
771+
if (arch != exe_arch) {
772+
err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
773+
}
774+
}
775+
if (!custom_release.is_empty() && FileAccess::exists(custom_release)) {
776+
String exe_arch = _get_exe_arch(custom_release);
777+
if (arch != exe_arch) {
778+
err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
779+
}
780+
}
781+
759782
String rcedit_path = EDITOR_GET("export/windows/rcedit");
760783
if (p_preset->get("application/modify_resources") && rcedit_path.is_empty()) {
761784
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<Edito
769792
}
770793

771794
bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
772-
String err = "";
795+
String err;
773796
bool valid = true;
774797

775798
List<ExportOption> options;
@@ -793,6 +816,43 @@ bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref<Edit
793816
return valid;
794817
}
795818

819+
String EditorExportPlatformWindows::_get_exe_arch(const String &p_path) const {
820+
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
821+
if (f.is_null()) {
822+
return "invalid";
823+
}
824+
825+
// Jump to the PE header and check the magic number.
826+
{
827+
f->seek(0x3c);
828+
uint32_t pe_pos = f->get_32();
829+
830+
f->seek(pe_pos);
831+
uint32_t magic = f->get_32();
832+
if (magic != 0x00004550) {
833+
return "invalid";
834+
}
835+
}
836+
837+
// Process header.
838+
uint16_t machine = f->get_16();
839+
f->close();
840+
841+
switch (machine) {
842+
case 0x014c:
843+
return "x86_32";
844+
case 0x8664:
845+
return "x86_64";
846+
case 0x01c0:
847+
case 0x01c4:
848+
return "arm32";
849+
case 0xaa64:
850+
return "arm64";
851+
default:
852+
return "unknown";
853+
}
854+
}
855+
796856
Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
797857
// Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data
798858

‎platform/windows/export/export_plugin.h

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC {
7373
Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon);
7474
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
7575

76+
String _get_exe_arch(const String &p_path) const;
77+
7678
public:
7779
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
7880
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) override;

0 commit comments

Comments
 (0)
Please sign in to comment.