handle BOMs in linker response files

Decode UTF-16LE response files with a BOM and strip UTF-8 BOMs before
parsing arguments. Add coverage for UTF-16 response-file input.
This commit is contained in:
Nikita Smith
2026-07-27 14:47:13 -07:00
committed by Ryan Fleury
parent 25430ea522
commit 35722f2a01
2 changed files with 26 additions and 0 deletions
+13
View File
@@ -711,6 +711,18 @@ lnk_parse_export_directive(Arena *arena, String8 directive, LNK_Obj *obj, PE_Exp
return is_parsed; return is_parsed;
} }
internal String8
lnk_text_file_string_from_data(Arena *arena, String8 data)
{
String8 result = data;
if (data.size >= 2 && data.str[0] == 0xff && data.str[1] == 0xfe) {
result = str8_from_16(arena, str16((U16 *)(data.str + 2), (data.size - 2) / sizeof(U16)));
} else if (data.size >= 3 && data.str[0] == 0xef && data.str[1] == 0xbb && data.str[2] == 0xbf) {
result = str8_skip(data, 3);
}
return result;
}
internal B32 internal B32
lnk_parse_merge_directive(String8 string, LNK_Obj *obj, LNK_MergeDirective *out) lnk_parse_merge_directive(String8 string, LNK_Obj *obj, LNK_MergeDirective *out)
{ {
@@ -1091,6 +1103,7 @@ lnk_unwrap_rsp(Arena *arena, String8List arg_list)
if (file_path_exists(name)) { if (file_path_exists(name)) {
// read rsp from disk // read rsp from disk
String8 file = lnk_read_data_from_file_path(scratch.arena, 0, name); String8 file = lnk_read_data_from_file_path(scratch.arena, 0, name);
file = lnk_text_file_string_from_data(scratch.arena, file);
// parse rsp // parse rsp
String8List rsp_args = lnk_arg_list_parse_windows_rules(scratch.arena, file); String8List rsp_args = lnk_arg_list_parse_windows_rules(scratch.arena, file);
+13
View File
@@ -2791,6 +2791,19 @@ TEST(import_export)
//T_Ok(t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /delayload:export.dll /export:entry kernel32.Lib delayimp.lib libcmt.lib export.lib import.obj entry.obj") == 0); //T_Ok(t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /delayload:export.dll /export:entry kernel32.Lib delayimp.lib libcmt.lib export.lib import.obj entry.obj") == 0);
// TODO: check import table // TODO: check import table
} }
TEST(utf16_rsp)
{
T_Ok(t_write_entry_obj());
String8 rsp_text = str8_lit("/subsystem:console /entry:entry /out:a.exe entry.obj\n");
String16 rsp16 = str16_from_8(arena, rsp_text);
String8 rsp_file = str8_cat(arena, str8_lit("\xff\xfe"), str8_array(rsp16.str, rsp16.size));
T_Ok(t_write_file(str8_lit("args.rsp"), rsp_file));
t_invoke_linkerf("@args.rsp");
T_Ok(g_last_exit_code == 0);
}
#endif #endif
TEST(image_base) TEST(image_base)