| ... | @@ -593,9 +593,9 @@ var ipc_metadata_len: u16 = 0; | ... | @@ -593,9 +593,9 @@ var ipc_metadata_len: u16 = 0; |
| 593 | | 593 | |
| 594 | const SavedMetadata = struct { | 594 | const SavedMetadata = struct { |
| 595 | ipc_fd: u16, | 595 | ipc_fd: u16, |
| 596 | main_index: u16, | 596 | main_index: u8, |
| 597 | start_index: u16, | 597 | start_index: u8, |
| 598 | nodes_len: u16, | 598 | nodes_len: u8, |
| 599 | | 599 | |
| 600 | fn getIpcFd(metadata: SavedMetadata) posix.fd_t { | 600 | fn getIpcFd(metadata: SavedMetadata) posix.fd_t { |
| 601 | return if (builtin.os.tag == .windows) | 601 | return if (builtin.os.tag == .windows) |
| ... | @@ -677,11 +677,13 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff | ... | @@ -677,11 +677,13 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff |
| 677 | }; | 677 | }; |
| 678 | }; | 678 | }; |
| 679 | | 679 | |
| | 680 | const nodes_len: u8 = @intCast(@min(parents.len - 1, serialized_buffer.storage.len - serialized_len)); |
| | 681 | |
| 680 | // Remember in case the pipe is empty on next update. | 682 | // Remember in case the pipe is empty on next update. |
| 681 | ipc_metadata[ipc_metadata_len] = .{ | 683 | ipc_metadata[ipc_metadata_len] = .{ |
| 682 | .ipc_fd = SavedMetadata.setIpcFd(fd), | 684 | .ipc_fd = SavedMetadata.setIpcFd(fd), |
| 683 | .start_index = @intCast(serialized_len), | 685 | .start_index = @intCast(serialized_len), |
| 684 | .nodes_len = @intCast(parents.len), | 686 | .nodes_len = nodes_len, |
| 685 | .main_index = @intCast(main_index), | 687 | .main_index = @intCast(main_index), |
| 686 | }; | 688 | }; |
| 687 | ipc_metadata_len += 1; | 689 | ipc_metadata_len += 1; |
| ... | @@ -690,24 +692,26 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff | ... | @@ -690,24 +692,26 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff |
| 690 | copyRoot(main_storage, &storage[0]); | 692 | copyRoot(main_storage, &storage[0]); |
| 691 | | 693 | |
| 692 | // Copy the rest of the tree to the end. | 694 | // 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]); |
| 694 | | 696 | |
| 695 | // Patch up parent pointers taking into account how the subtree is mounted. | 697 | // Patch up parent pointers taking into account how the subtree is mounted. |
| 696 | serialized_buffer.parents[serialized_len] = .none; | 698 | for (serialized_buffer.parents[serialized_len..][0..nodes_len], parents[1..][0..nodes_len]) |*dest, p| { |
| 697 | | | |
| 698 | for (serialized_buffer.parents[serialized_len..][0 .. parents.len - 1], parents[1..]) |*dest, p| { | | |
| 699 | dest.* = switch (p) { | 699 | dest.* = switch (p) { |
| 700 | // Fix bad data so the rest of the code does not see `unused`. | 700 | // Fix bad data so the rest of the code does not see `unused`. |
| 701 | .none, .unused => .none, | 701 | .none, .unused => .none, |
| 702 | // Root node is being mounted here. | 702 | // Root node is being mounted here. |
| 703 | @as(Node.Parent, @enumFromInt(0)) => @enumFromInt(main_index), | 703 | @as(Node.Parent, @enumFromInt(0)) => @enumFromInt(main_index), |
| 704 | // Other nodes mounted at the end. | 704 | // Other nodes mounted at the end. |
| 705 | // TODO check for bad data pointing outside the expected range | 705 | // Don't trust child data; if the data is outside the expected range, ignore the data. |
| 706 | _ => |off| @enumFromInt(serialized_len + @intFromEnum(off) - 1), | 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), |
| 707 | }; | 711 | }; |
| 708 | } | 712 | } |
| 709 | | 713 | |
| 710 | serialized_len += storage.len - 1; | 714 | serialized_len += nodes_len; |
| 711 | } | 715 | } |
| 712 | | 716 | |
| 713 | // Save a copy in case any pipes are empty on the next update. | 717 | // Save a copy in case any pipes are empty on the next update. |
| ... | @@ -753,7 +757,7 @@ fn useSavedIpcData( | ... | @@ -753,7 +757,7 @@ fn useSavedIpcData( |
| 753 | }; | 757 | }; |
| 754 | | 758 | |
| 755 | const start_index = saved_metadata.start_index; | 759 | 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); |
| 757 | const old_main_index = saved_metadata.main_index; | 761 | const old_main_index = saved_metadata.main_index; |
| 758 | | 762 | |
| 759 | ipc_metadata[ipc_metadata_len] = .{ | 763 | ipc_metadata[ipc_metadata_len] = .{ |
| ... | @@ -764,8 +768,8 @@ fn useSavedIpcData( | ... | @@ -764,8 +768,8 @@ fn useSavedIpcData( |
| 764 | }; | 768 | }; |
| 765 | ipc_metadata_len += 1; | 769 | ipc_metadata_len += 1; |
| 766 | | 770 | |
| 767 | const parents = parents_copy[start_index..][0 .. nodes_len - 1]; | 771 | const parents = parents_copy[start_index..][0..nodes_len]; |
| 768 | const storage = storage_copy[start_index..][0 .. nodes_len - 1]; | 772 | const storage = storage_copy[start_index..][0..nodes_len]; |
| 769 | | 773 | |
| 770 | copyRoot(main_storage, &storage_copy[old_main_index]); | 774 | copyRoot(main_storage, &storage_copy[old_main_index]); |
| 771 | | 775 | |
| ... | @@ -774,10 +778,15 @@ fn useSavedIpcData( | ... | @@ -774,10 +778,15 @@ fn useSavedIpcData( |
| 774 | for (serialized_buffer.parents[start_serialized_len..][0..parents.len], parents) |*dest, p| { | 778 | for (serialized_buffer.parents[start_serialized_len..][0..parents.len], parents) |*dest, p| { |
| 775 | dest.* = switch (p) { | 779 | dest.* = switch (p) { |
| 776 | .none, .unused => .none, | 780 | .none, .unused => .none, |
| 777 | _ => |prev| @enumFromInt(if (@intFromEnum(prev) == old_main_index) | 781 | _ => |prev| d: { |
| 778 | main_index | 782 | if (@intFromEnum(prev) == old_main_index) { |
| 779 | else | 783 | break :d @enumFromInt(main_index); |
| 780 | @intFromEnum(prev) - start_index + start_serialized_len), | 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 | }, |
| 781 | }; | 790 | }; |
| 782 | } | 791 | } |
| 783 | | 792 | |