| ... | ... | @@ -409,6 +409,7 @@ pub const Manifest = struct { |
| 409 | 409 | |
| 410 | 410 | pub fn getFallible(offset: Offset, contents: []u8) error{InvalidFormat}!*File { |
| 411 | 411 | if (@backingInt(offset) + @sizeOf(File) >= contents.len) return error.InvalidFormat; |
| 412 | if (!mem.isAligned(@backingInt(offset), @alignOf(File))) return error.InvalidFormat; |
| 412 | 413 | return get(offset, contents); |
| 413 | 414 | } |
| 414 | 415 | }; |
| ... | ... | @@ -458,6 +459,14 @@ pub const Manifest = struct { |
| 458 | 459 | return true; |
| 459 | 460 | } |
| 460 | 461 | } |
| 462 | |
| 463 | /// `path_len` does not include the null byte. |
| 464 | fn sizeOf(path_len: usize) usize { |
| 465 | const end = @offsetOf(File, "path_start") + path_len; |
| 466 | const needed_alignment = @alignOf(File) - (end % @alignOf(File)); |
| 467 | assert(needed_alignment >= 1); // Always need at least a null byte. |
| 468 | return end + needed_alignment; |
| 469 | } |
| 461 | 470 | }; |
| 462 | 471 | |
| 463 | 472 | pub const Diagnostic = union(enum) { |
| ... | ... | @@ -809,7 +818,7 @@ pub const Manifest = struct { |
| 809 | 818 | }; |
| 810 | 819 | const contents = m.contents.items; |
| 811 | 820 | |
| 812 | | var off: u32 = 0; |
| 821 | var off: usize = 0; |
| 813 | 822 | var c: Check = .{}; |
| 814 | 823 | |
| 815 | 824 | // This group we always want to compute the hash digests, even on a |
| ... | ... | @@ -821,7 +830,7 @@ pub const Manifest = struct { |
| 821 | 830 | // otherwise it's invalid format. |
| 822 | 831 | for (m.input_paths.items, m.files.keys()[0..m.input_paths.items.len]) |*input_path, input_file_off| { |
| 823 | 832 | if (off + 1 >= contents.len) return error.InvalidFormat; |
| 824 | | const file_off: File.Offset = @fromBackingInt(off); |
| 833 | const file_off: File.Offset = @fromBackingInt(@intCast(off)); |
| 825 | 834 | const file = try file_off.getFallible(contents); |
| 826 | 835 | if (file.flags.prefix >= m.cache.prefixes_len) return error.InvalidFormat; |
| 827 | 836 | const path = try filePathFallible(contents, file_off); |
| ... | ... | @@ -830,7 +839,7 @@ pub const Manifest = struct { |
| 830 | 839 | |
| 831 | 840 | input_group.async(io, checkInputFile, .{ m, &c, file_off, path, input_path }); |
| 832 | 841 | |
| 833 | | off = @intCast(@as(usize, off) + @sizeOf(File) + path.len + 1); |
| 842 | off += File.sizeOf(path.len); |
| 834 | 843 | } |
| 835 | 844 | |
| 836 | 845 | // Guess number of files based on manifest contents len to reduce allocations. |
| ... | ... | @@ -849,7 +858,7 @@ pub const Manifest = struct { |
| 849 | 858 | defer post_select.cancelDiscard(); |
| 850 | 859 | |
| 851 | 860 | while (off + 1 < contents.len) { |
| 852 | | const file_off: File.Offset = @fromBackingInt(off); |
| 861 | const file_off: File.Offset = @fromBackingInt(@intCast(off)); |
| 853 | 862 | const file = try file_off.getFallible(contents); |
| 854 | 863 | if (file.flags.prefix >= m.cache.prefixes_len) return error.InvalidFormat; |
| 855 | 864 | const path = try filePathFallible(contents, file_off); |
| ... | ... | @@ -860,7 +869,7 @@ pub const Manifest = struct { |
| 860 | 869 | post_select.async(.checkFile, checkFile, .{ m, &c, file_off, path }); |
| 861 | 870 | post_select_remaining += 1; |
| 862 | 871 | |
| 863 | | off = @intCast(@as(usize, off) + @sizeOf(File) + path.len + 1); |
| 872 | off += File.sizeOf(path.len); |
| 864 | 873 | } |
| 865 | 874 | |
| 866 | 875 | // Final terminating zero byte to distinguish empty manifest file from |