Skip to content

Commit

Permalink
package fetching: catch relative paths that resolve into cache dir
Browse files Browse the repository at this point in the history
The logic here already caught the case when a dependency path tried to
escape out of the zig cache directory using up directories. However, it
did not catch the case when the relative path tried to reach into a
different path within the zig-cache. For example, if it asked for
"../../../blah" then it would be caught, but if it asked for "../blah"
then it would try to resolve as "zig-cache/p/blah" and probably result
in file-not-found, or perhaps resolve to a different package if someone
inadvertently used a valid package hash instead of "blah".

Now it correctly gives a "dependency path outside project" error,
however, still allows relative paths with up-dirs that were not fetched
via URL.
  • Loading branch information
andrewrk committed Nov 28, 2023
1 parent a98d4a6 commit 2a32264
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions src/Package/Fetch.zig
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,22 @@ pub fn run(f: *Fetch) RunError!void {
f.hash_tok,
try eb.addString("path-based dependencies are not hashed"),
);
if ((std.mem.startsWith(u8, pkg_root.sub_path, "../") or
std.mem.eql(u8, pkg_root.sub_path, "..")) and
pkg_root.root_dir.eql(cache_root))
{
return f.fail(
f.location_tok,
try eb.printString("dependency path outside project: '{}{s}'", .{
pkg_root.root_dir, pkg_root.sub_path,
}),
);
// Packages fetched by URL may not use relative paths to escape outside the
// fetched package directory from within the package cache.
if (pkg_root.root_dir.eql(cache_root)) {
// `parent_package_root.sub_path` contains a path like this:
// "p/$hash", or
// "p/$hash/foo", with possibly more directories after "foo".
// We want to fail unless the resolved relative path has a
// prefix of "p/$hash/".
const digest_len = @typeInfo(Manifest.MultiHashHexDigest).Array.len;
const expected_prefix = f.parent_package_root.sub_path[0 .. "p/".len + digest_len];
if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {
return f.fail(
f.location_tok,
try eb.printString("dependency path outside project: '{}'", .{pkg_root}),
);
}
}
f.package_root = pkg_root;
try loadManifest(f, pkg_root);
Expand Down

0 comments on commit 2a32264

Please sign in to comment.