| ... | ... | @@ -123,15 +123,16 @@ fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath { |
| 123 | 123 | var i: u8 = 1; // Start at 1 to skip over checking the null prefix. |
| 124 | 124 | while (i < prefixes_slice.len) : (i += 1) { |
| 125 | 125 | const p = prefixes_slice[i].path.?; |
| 126 | | if (p.len > 0 and mem.startsWith(u8, resolved_path, p)) { |
| 127 | | // +1 to skip over the path separator here |
| 128 | | const sub_path = try gpa.dupe(u8, resolved_path[p.len + 1 ..]); |
| 129 | | gpa.free(resolved_path); |
| 130 | | return PrefixedPath{ |
| 131 | | .prefix = @as(u8, @intCast(i)), |
| 132 | | .sub_path = sub_path, |
| 133 | | }; |
| 134 | | } |
| 126 | var sub_path = getPrefixSubpath(gpa, p, resolved_path) catch |err| switch (err) { |
| 127 | error.NotASubPath => continue, |
| 128 | else => |e| return e, |
| 129 | }; |
| 130 | // Free the resolved path since we're not going to return it |
| 131 | gpa.free(resolved_path); |
| 132 | return PrefixedPath{ |
| 133 | .prefix = i, |
| 134 | .sub_path = sub_path, |
| 135 | }; |
| 135 | 136 | } |
| 136 | 137 | |
| 137 | 138 | return PrefixedPath{ |
| ... | ... | @@ -140,6 +141,22 @@ fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath { |
| 140 | 141 | }; |
| 141 | 142 | } |
| 142 | 143 | |
| 144 | fn getPrefixSubpath(allocator: Allocator, prefix: []const u8, path: []u8) ![]u8 { |
| 145 | const relative = try std.fs.path.relative(allocator, prefix, path); |
| 146 | errdefer allocator.free(relative); |
| 147 | var component_iterator = std.fs.path.NativeUtf8ComponentIterator.init(relative) catch { |
| 148 | return error.NotASubPath; |
| 149 | }; |
| 150 | if (component_iterator.root() != null) { |
| 151 | return error.NotASubPath; |
| 152 | } |
| 153 | const first_component = component_iterator.first(); |
| 154 | if (first_component != null and std.mem.eql(u8, first_component.?.name, "..")) { |
| 155 | return error.NotASubPath; |
| 156 | } |
| 157 | return relative; |
| 158 | } |
| 159 | |
| 143 | 160 | /// This is 128 bits - Even with 2^54 cache entries, the probably of a collision would be under 10^-6 |
| 144 | 161 | pub const bin_digest_len = 16; |
| 145 | 162 | pub const hex_digest_len = bin_digest_len * 2; |
| ... | ... | @@ -734,7 +751,7 @@ pub const Manifest = struct { |
| 734 | 751 | resolved_path: []u8, |
| 735 | 752 | bytes: []const u8, |
| 736 | 753 | stat: File.Stat, |
| 737 | | ) error{OutOfMemory}!void { |
| 754 | ) !void { |
| 738 | 755 | assert(self.manifest_file != null); |
| 739 | 756 | const gpa = self.cache.gpa; |
| 740 | 757 | |