From 7b890ff9789caf010639277168d5f5852a9d852e Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 13 Aug 2026 21:44:18 -0700 Subject: [PATCH] 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 --- src/Compilation.zig | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index f6b30ef3f9c1c91abf29381d6b9d2b273ef6a424..c79afb0923996fb4c41afb1d42fe80809149d130 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -484,8 +484,13 @@ pub const Path = struct { assert(fs.path.isAbsolute(sub_path)); if (!std.mem.startsWith(u8, sub_path, cwd_path)) return sub_path; if (sub_path.len == cwd_path.len) return "."; // the strings are equal - if (sub_path[cwd_path.len] != fs.path.sep) return sub_path; // last component before cwd differs - return sub_path[cwd_path.len + 1 ..]; // remove '/path/to/cwd/' prefix + const path_sep_index = path_sep_index: { + // cwd is just a root, e.g. / or C:\ + if (cwd_path[cwd_path.len - 1] == fs.path.sep) break :path_sep_index cwd_path.len - 1; + if (sub_path[cwd_path.len] != fs.path.sep) return sub_path; // last component before cwd differs + break :path_sep_index cwd_path.len; + }; + return sub_path[path_sep_index + 1 ..]; // remove '/path/to/cwd/' prefix } /// From an unresolved path (which can be made of multiple not-yet-joined strings), construct a @@ -672,8 +677,13 @@ pub const Path = struct { if (!mem.startsWith(u8, inner.sub_path, outer.sub_path)) return .no; if (inner.sub_path.len == outer.sub_path.len) return .no; if (outer.sub_path.len == 0) return .{ .yes = inner.sub_path }; - if (inner.sub_path[outer.sub_path.len] != fs.path.sep) return .no; - return .{ .yes = inner.sub_path[outer.sub_path.len + 1 ..] }; + const path_sep_index = path_sep_index: { + // outer is just a root, e.g. / or C:\ + if (outer.sub_path[outer.sub_path.len - 1] == fs.path.sep) break :path_sep_index outer.sub_path.len - 1; + if (inner.sub_path[outer.sub_path.len] != fs.path.sep) return .no; + break :path_sep_index outer.sub_path.len; + }; + return .{ .yes = inner.sub_path[path_sep_index + 1 ..] }; } /// Returns whether this `Path` is illegal to have as a user-imported `Zcu.File` (including -- 2.54.0