authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-25 19:56:44-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-26 19:08:50-04:00
loge0beb0222312a5c4737ccfe76e75e414f594bd9a
tree721d74b231e567ce866e3c1ddea45795dc6fbacf
parent2cdf284af96ea016a5553ae9f6516b9b2c8f3f8e

Runner: fix crashes caused by noop mutations of read-only data

`std.Io.Reader.ending` is pretty much unusable, so just make my own on the stack.

1 files changed, 29 insertions(+), 6 deletions(-)

test/src/Runner.zig+29-6
......@@ -598,10 +598,10 @@ fn testOne(runner: *Runner, test_index: u32) TestError!void {
598598 defer if (contents_file) |file| file.close(runner.io);
599599 var contents_buffer: [512]u8 = undefined;
600600 var contents_impl: union(enum) {
601 ending,
601 ending: std.Io.Reader,
602602 dr: DelimitedReader,
603603 fr: std.Io.File.Reader,
604 } = .ending;
604 } = undefined;
605605 const contents_r: *std.Io.Reader = contents_r: switch (cmd) {
606606 .skip, .delete => {
607607 const unexpected = line_it.rest();
......@@ -610,11 +610,15 @@ fn testOne(runner: *Runner, test_index: u32) TestError!void {
610610 "unexpected argument {q}",
611611 .{unexpected},
612612 );
613 break :contents_r .ending;
613 contents_impl = .{ .ending = .ending_instance };
614 break :contents_r &contents_impl.ending;
614615 },
615616 else => {
616617 const contents_path = line_it.rest();
617 if (contents_path.len == 0) break :contents_r .ending;
618 if (contents_path.len == 0) {
619 contents_impl = .{ .ending = .ending_instance };
620 break :contents_r &contents_impl.ending;
621 }
618622
619623 if (std.mem.eql(u8, contents_path, "{")) {
620624 contents_impl = .{
......@@ -743,8 +747,27 @@ fn handleCommand(
743747 else => |e| return update.manifest_sr.fail(arg.?, "unable to create file: {t}", .{e}),
744748 };
745749 defer file.close(runner.io);
746 var fw = file.writer(runner.io, &.{});
747 _ = try contents_r.streamRemaining(&fw.interface);
750 var fw_buffer: [512]u8 = undefined;
751 var fw = file.writer(runner.io, &fw_buffer);
752 _ = contents_r.streamRemaining(&fw.interface) catch |err| switch (err) {
753 error.ReadFailed => |e| return e,
754 error.WriteFailed => switch (fw.err.?) {
755 error.Canceled => |e| return e,
756 else => |e| return update.manifest_sr.fail(
757 arg.?,
758 "unable to write file: {t}",
759 .{e},
760 ),
761 },
762 };
763 fw.flush() catch |err| switch (err) {
764 error.Canceled => |e| return e,
765 else => |e| return update.manifest_sr.fail(
766 arg.?,
767 "unable to write file: {t}",
768 .{e},
769 ),
770 };
748771 file.setTimestamps(runner.io, .{ .modify_timestamp = .{
749772 .new = update.mtime,
750773 } }) catch |err| switch (err) {