authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-26 16:05:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 20:56:48-07:00
log52ed54d1e7a396f4508829af45c6953f1a827a1c
tree3b2756974b8ed75be3cf1b79fb45476599fe1632
parent807b613f71bf97d8169b6ce3ed7ad0c0dc8bb402

std.Progress: truncate IPC data exceeding preallocated buffers

This accomplishes 2 things simultaneously: 1. Don't trust child process data; if the data is outside the expected range, ignore the data. 2. If there is too much data to fit in the preallocated buffers, drop the data.

1 files changed, 27 insertions(+), 18 deletions(-)

lib/std/Progress.zig+27-18
......@@ -593,9 +593,9 @@ var ipc_metadata_len: u16 = 0;
593593
594594const SavedMetadata = struct {
595595 ipc_fd: u16,
596 main_index: u16,
597 start_index: u16,
598 nodes_len: u16,
596 main_index: u8,
597 start_index: u8,
598 nodes_len: u8,
599599
600600 fn getIpcFd(metadata: SavedMetadata) posix.fd_t {
601601 return if (builtin.os.tag == .windows)
......@@ -677,11 +677,13 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
677677 };
678678 };
679679
680 const nodes_len: u8 = @intCast(@min(parents.len - 1, serialized_buffer.storage.len - serialized_len));
681
680682 // Remember in case the pipe is empty on next update.
681683 ipc_metadata[ipc_metadata_len] = .{
682684 .ipc_fd = SavedMetadata.setIpcFd(fd),
683685 .start_index = @intCast(serialized_len),
684 .nodes_len = @intCast(parents.len),
686 .nodes_len = nodes_len,
685687 .main_index = @intCast(main_index),
686688 };
687689 ipc_metadata_len += 1;
......@@ -690,24 +692,26 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
690692 copyRoot(main_storage, &storage[0]);
691693
692694 // Copy the rest of the tree to the end.
693 @memcpy(serialized_buffer.storage[serialized_len..][0 .. storage.len - 1], storage[1..]);
695 @memcpy(serialized_buffer.storage[serialized_len..][0..nodes_len], storage[1..][0..nodes_len]);
694696
695697 // Patch up parent pointers taking into account how the subtree is mounted.
696 serialized_buffer.parents[serialized_len] = .none;
697
698 for (serialized_buffer.parents[serialized_len..][0 .. parents.len - 1], parents[1..]) |*dest, p| {
698 for (serialized_buffer.parents[serialized_len..][0..nodes_len], parents[1..][0..nodes_len]) |*dest, p| {
699699 dest.* = switch (p) {
700700 // Fix bad data so the rest of the code does not see `unused`.
701701 .none, .unused => .none,
702702 // Root node is being mounted here.
703703 @as(Node.Parent, @enumFromInt(0)) => @enumFromInt(main_index),
704704 // Other nodes mounted at the end.
705 // TODO check for bad data pointing outside the expected range
706 _ => |off| @enumFromInt(serialized_len + @intFromEnum(off) - 1),
705 // Don't trust child data; if the data is outside the expected range, ignore the data.
706 // This also handles the case when data was truncated.
707 _ => |off| if (@intFromEnum(off) > nodes_len)
708 .none
709 else
710 @enumFromInt(serialized_len + @intFromEnum(off) - 1),
707711 };
708712 }
709713
710 serialized_len += storage.len - 1;
714 serialized_len += nodes_len;
711715 }
712716
713717 // Save a copy in case any pipes are empty on the next update.
......@@ -753,7 +757,7 @@ fn useSavedIpcData(
753757 };
754758
755759 const start_index = saved_metadata.start_index;
756 const nodes_len = saved_metadata.nodes_len;
760 const nodes_len = @min(saved_metadata.nodes_len, serialized_buffer.storage.len - start_serialized_len);
757761 const old_main_index = saved_metadata.main_index;
758762
759763 ipc_metadata[ipc_metadata_len] = .{
......@@ -764,8 +768,8 @@ fn useSavedIpcData(
764768 };
765769 ipc_metadata_len += 1;
766770
767 const parents = parents_copy[start_index..][0 .. nodes_len - 1];
768 const storage = storage_copy[start_index..][0 .. nodes_len - 1];
771 const parents = parents_copy[start_index..][0..nodes_len];
772 const storage = storage_copy[start_index..][0..nodes_len];
769773
770774 copyRoot(main_storage, &storage_copy[old_main_index]);
771775
......@@ -774,10 +778,15 @@ fn useSavedIpcData(
774778 for (serialized_buffer.parents[start_serialized_len..][0..parents.len], parents) |*dest, p| {
775779 dest.* = switch (p) {
776780 .none, .unused => .none,
777 _ => |prev| @enumFromInt(if (@intFromEnum(prev) == old_main_index)
778 main_index
779 else
780 @intFromEnum(prev) - start_index + start_serialized_len),
781 _ => |prev| d: {
782 if (@intFromEnum(prev) == old_main_index) {
783 break :d @enumFromInt(main_index);
784 } else if (@intFromEnum(prev) > nodes_len) {
785 break :d .none;
786 } else {
787 break :d @enumFromInt(@intFromEnum(prev) - start_index + start_serialized_len);
788 }
789 },
781790 };
782791 }
783792