authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-08-13 21:44:18-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-08-14 12:25:13+02:00
log7b890ff9789caf010639277168d5f5852a9d852e
treea7f36a8e130d9bb5b0a285b8dc7b48a369b9d058
parent63cfe88f0c011895fdd573703ad6715ec91e3231

Fix Compilation.Path checks when one path is a root path

Previously, it was assumed that the byte after the cwd/outer path had to be a path separator, but that's not true when the cwd/outer path is a root with no components (e.g. `/` or `C:\`) Fixes #32005

1 files changed, 14 insertions(+), 4 deletions(-)

src/Compilation.zig+14-4
......@@ -484,8 +484,13 @@ pub const Path = struct {
484484 assert(fs.path.isAbsolute(sub_path));
485485 if (!std.mem.startsWith(u8, sub_path, cwd_path)) return sub_path;
486486 if (sub_path.len == cwd_path.len) return "."; // the strings are equal
487 if (sub_path[cwd_path.len] != fs.path.sep) return sub_path; // last component before cwd differs
488 return sub_path[cwd_path.len + 1 ..]; // remove '/path/to/cwd/' prefix
487 const path_sep_index = path_sep_index: {
488 // cwd is just a root, e.g. / or C:\
489 if (cwd_path[cwd_path.len - 1] == fs.path.sep) break :path_sep_index cwd_path.len - 1;
490 if (sub_path[cwd_path.len] != fs.path.sep) return sub_path; // last component before cwd differs
491 break :path_sep_index cwd_path.len;
492 };
493 return sub_path[path_sep_index + 1 ..]; // remove '/path/to/cwd/' prefix
489494 }
490495
491496 /// From an unresolved path (which can be made of multiple not-yet-joined strings), construct a
......@@ -672,8 +677,13 @@ pub const Path = struct {
672677 if (!mem.startsWith(u8, inner.sub_path, outer.sub_path)) return .no;
673678 if (inner.sub_path.len == outer.sub_path.len) return .no;
674679 if (outer.sub_path.len == 0) return .{ .yes = inner.sub_path };
675 if (inner.sub_path[outer.sub_path.len] != fs.path.sep) return .no;
676 return .{ .yes = inner.sub_path[outer.sub_path.len + 1 ..] };
680 const path_sep_index = path_sep_index: {
681 // outer is just a root, e.g. / or C:\
682 if (outer.sub_path[outer.sub_path.len - 1] == fs.path.sep) break :path_sep_index outer.sub_path.len - 1;
683 if (inner.sub_path[outer.sub_path.len] != fs.path.sep) return .no;
684 break :path_sep_index outer.sub_path.len;
685 };
686 return .{ .yes = inner.sub_path[path_sep_index + 1 ..] };
677687 }
678688
679689 /// Returns whether this `Path` is illegal to have as a user-imported `Zcu.File` (including