Add Windows PE codesigning support for standalone executables (#21091)

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
jarred-sumner-bot
2025-07-15 22:31:54 -07:00
committed by GitHub
parent 0ce70df96b
commit 32ce9a3890
6 changed files with 902 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ const SourceMap = bun.sourcemap;
const StringPointer = bun.StringPointer;
const macho = bun.macho;
const pe = bun.pe;
const w = std.os.windows;
pub const StandaloneModuleGraph = struct {
@@ -137,6 +138,19 @@ pub const StandaloneModuleGraph = struct {
}
};
const PE = struct {
pub extern "C" fn Bun__getStandaloneModuleGraphPELength() u32;
pub extern "C" fn Bun__getStandaloneModuleGraphPEData() ?[*]u8;
pub fn getData() ?[]const u8 {
const length = Bun__getStandaloneModuleGraphPELength();
if (length == 0) return null;
const data_ptr = Bun__getStandaloneModuleGraphPEData() orelse return null;
return data_ptr[0..length];
}
};
pub const File = struct {
name: []const u8 = "",
loader: bun.options.Loader,
@@ -682,6 +696,44 @@ pub const StandaloneModuleGraph = struct {
}
return cloned_executable_fd;
},
.windows => {
const input_result = bun.sys.File.readToEnd(.{ .handle = cloned_executable_fd }, bun.default_allocator);
if (input_result.err) |err| {
Output.prettyErrorln("Error reading standalone module graph: {}", .{err});
cleanup(zname, cloned_executable_fd);
Global.exit(1);
}
var pe_file = bun.pe.PEFile.init(bun.default_allocator, input_result.bytes.items) catch |err| {
Output.prettyErrorln("Error initializing PE file: {}", .{err});
cleanup(zname, cloned_executable_fd);
Global.exit(1);
};
defer pe_file.deinit();
pe_file.addBunSection(bytes) catch |err| {
Output.prettyErrorln("Error adding Bun section to PE file: {}", .{err});
cleanup(zname, cloned_executable_fd);
Global.exit(1);
};
input_result.bytes.deinit();
switch (Syscall.setFileOffset(cloned_executable_fd, 0)) {
.err => |err| {
Output.prettyErrorln("Error seeking to start of temporary file: {}", .{err});
cleanup(zname, cloned_executable_fd);
Global.exit(1);
},
else => {},
}
var file = bun.sys.File{ .handle = cloned_executable_fd };
const writer = file.writer();
pe_file.write(writer) catch |err| {
Output.prettyErrorln("Error writing PE file: {}", .{err});
cleanup(zname, cloned_executable_fd);
Global.exit(1);
};
return cloned_executable_fd;
},
else => {
var total_byte_count: usize = undefined;
if (Environment.isWindows) {
@@ -888,6 +940,22 @@ pub const StandaloneModuleGraph = struct {
return try StandaloneModuleGraph.fromBytes(allocator, @constCast(macho_bytes), offsets);
}
if (comptime Environment.isWindows) {
const pe_bytes = PE.getData() orelse return null;
if (pe_bytes.len < @sizeOf(Offsets) + trailer.len) {
Output.debugWarn("bun standalone module graph is too small to be valid", .{});
return null;
}
const pe_bytes_slice = pe_bytes[pe_bytes.len - @sizeOf(Offsets) - trailer.len ..];
const trailer_bytes = pe_bytes[pe_bytes.len - trailer.len ..][0..trailer.len];
if (!bun.strings.eqlComptime(trailer_bytes, trailer)) {
Output.debugWarn("bun standalone module graph has invalid trailer", .{});
return null;
}
const offsets = std.mem.bytesAsValue(Offsets, pe_bytes_slice).*;
return try StandaloneModuleGraph.fromBytes(allocator, @constCast(pe_bytes), offsets);
}
// Do not invoke libuv here.
const self_exe = openSelf() catch return null;
defer self_exe.close();