mirror of
https://github.com/ziglang/zig.git
synced 2024-11-16 17:15:37 +00:00
stdlib: escape backslashes and double quotes in Builder response file
Fixes #11595
This commit is contained in:
parent
d7f8368da8
commit
94b9bcd034
@ -3009,6 +3009,7 @@ pub const LibExeObjStep = struct {
|
||||
// Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux
|
||||
// 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and
|
||||
// pass that to zig, e.g. via 'zig build-lib @args.rsp'
|
||||
// See @file syntax here: https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html
|
||||
var args_length: usize = 0;
|
||||
for (zig_args.items) |arg| {
|
||||
args_length += arg.len + 1; // +1 to account for null terminator
|
||||
@ -3020,9 +3021,33 @@ pub const LibExeObjStep = struct {
|
||||
);
|
||||
try std.fs.cwd().makePath(args_dir);
|
||||
|
||||
var args_arena = std.heap.ArenaAllocator.init(builder.allocator);
|
||||
defer args_arena.deinit();
|
||||
|
||||
const args_to_escape = zig_args.items[2..];
|
||||
var escaped_args = try ArrayList([]const u8).initCapacity(args_arena.allocator(), args_to_escape.len);
|
||||
|
||||
arg_blk: for (args_to_escape) |arg| {
|
||||
for (arg) |c, arg_idx| {
|
||||
if (c == '\\' or c == '"') {
|
||||
// Slow path for arguments that need to be escaped. We'll need to allocate and copy
|
||||
var escaped = try ArrayList(u8).initCapacity(args_arena.allocator(), arg.len + 1);
|
||||
const writer = escaped.writer();
|
||||
writer.writeAll(arg[0..arg_idx]) catch unreachable;
|
||||
for (arg[arg_idx..]) |to_escape| {
|
||||
if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\');
|
||||
try writer.writeByte(to_escape);
|
||||
}
|
||||
escaped_args.appendAssumeCapacity(escaped.items);
|
||||
continue :arg_blk;
|
||||
}
|
||||
}
|
||||
escaped_args.appendAssumeCapacity(arg); // no escaping needed so just use original argument
|
||||
}
|
||||
|
||||
// Write the args to zig-cache/args/<SHA256 hash of args> to avoid conflicts with
|
||||
// other zig build commands running in parallel.
|
||||
const partially_quoted = try std.mem.join(builder.allocator, "\" \"", zig_args.items[2..]);
|
||||
const partially_quoted = try std.mem.join(builder.allocator, "\" \"", escaped_args.items);
|
||||
const args = try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "\"", partially_quoted, "\"" });
|
||||
|
||||
var args_hash: [Sha256.digest_length]u8 = undefined;
|
||||
|
@ -49,6 +49,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
|
||||
cases.addBuildFile("test/standalone/issue_7030/build.zig", .{});
|
||||
cases.addBuildFile("test/standalone/install_raw_hex/build.zig", .{});
|
||||
cases.addBuildFile("test/standalone/issue_9812/build.zig", .{});
|
||||
cases.addBuildFile("test/standalone/issue_11595/build.zig", .{});
|
||||
if (builtin.os.tag != .wasi) {
|
||||
cases.addBuildFile("test/standalone/load_dynamic_library/build.zig", .{});
|
||||
}
|
||||
|
52
test/standalone/issue_11595/build.zig
Normal file
52
test/standalone/issue_11595/build.zig
Normal file
@ -0,0 +1,52 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
// TODO integrate this with the std.build executor API
|
||||
fn isRunnableTarget(t: CrossTarget) bool {
|
||||
if (t.isNative()) return true;
|
||||
|
||||
return (t.getOsTag() == builtin.os.tag and
|
||||
t.getCpuArch() == builtin.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const exe = b.addExecutable("zigtest", "main.zig");
|
||||
exe.setBuildMode(mode);
|
||||
exe.install();
|
||||
|
||||
const c_sources = [_][]const u8{
|
||||
"test.c",
|
||||
};
|
||||
|
||||
exe.addCSourceFiles(&c_sources, &.{});
|
||||
exe.linkLibC();
|
||||
|
||||
var i: i32 = 0;
|
||||
while (i < 1000) : (i += 1) {
|
||||
exe.defineCMacro("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
}
|
||||
|
||||
exe.defineCMacro("FOO", "42");
|
||||
exe.defineCMacro("BAR", "\"BAR\"");
|
||||
exe.defineCMacro("BAZ",
|
||||
\\"\"BAZ\""
|
||||
);
|
||||
exe.defineCMacro("QUX", "\"Q\" \"UX\"");
|
||||
exe.defineCMacro("QUUX", "\"QU\\\"UX\"");
|
||||
|
||||
exe.setTarget(target);
|
||||
b.default_step.dependOn(&exe.step);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
if (isRunnableTarget(target)) {
|
||||
const run_cmd = exe.run();
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
} else {
|
||||
test_step.dependOn(&exe.step);
|
||||
}
|
||||
}
|
5
test/standalone/issue_11595/main.zig
Normal file
5
test/standalone/issue_11595/main.zig
Normal file
@ -0,0 +1,5 @@
|
||||
extern fn check() c_int;
|
||||
|
||||
pub fn main() u8 {
|
||||
return @intCast(u8, check());
|
||||
}
|
10
test/standalone/issue_11595/test.c
Normal file
10
test/standalone/issue_11595/test.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <string.h>
|
||||
|
||||
int check(void) {
|
||||
if (FOO != 42) return 1;
|
||||
if (strcmp(BAR, "BAR")) return 2;
|
||||
if (strcmp(BAZ, "\"BAZ\"")) return 3;
|
||||
if (strcmp(QUX, "QUX")) return 4;
|
||||
if (strcmp(QUUX, "QU\"UX")) return 5;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user