Skip to content

builtins.path and builtins.filterSource use wrong filter paths with --store argument #11503

@Yarny0

Description

@Yarny0

Describe the bug

The built-in functions builtins.path or builtins.filterSource both accept a root path and a filter function. The filter function is then called with subpaths of the root path as argument. Under certain circumstances, those subpaths are in fact not subpaths of the root path. As far as I could investigate, this happens if

  • the --store argument is used to point to another store that is not the "canonical" store ("canonical" usually is /nix/store),
  • the nix file that is evaluate and that contains the call to a built-in function is itself positioned in the "canonical" nix store,
  • the root directory points to ./., and
  • the derivation that contains the nix file is also present in the other nix store.

Note that these circumstances are usually given when you install NixOS from a live iso with nixos-install: Most nix files involved are contained in the nixos channel, which is somewhere in /nix/store. This channel is copied to /mnt/nix/store by nixos-install before anything else is done.

Steps To Reproduce

Put these two files in the same directory, then execute test.sh (this expects Nix to be installed and accessible, but no root privileges):

test.nix
let
  root = ./.;
  filter = path: type:
    let
      rootStr = builtins.toString ./.;
    in
      if builtins.substring 0 (builtins.stringLength rootStr) (builtins.toString path) == rootStr then true
      else builtins.throw "root path\n${rootStr}\nnot prefix of path\n${builtins.toString path}";
in

# each one will demonstrate the problem!:
#builtins.path { name="name"; path=root; inherit filter; }
builtins.filterSource filter root
test.sh
#! /usr/bin/env bash
tmpdir=$(mktemp -d)
mkdir $tmpdir/directory
cp test.nix $tmpdir/directory/default.nix
result=$(nix-store --add-fixed --recursive sha256 $tmpdir/directory)
nix-instantiate --eval $result
nix-instantiate --eval $result --store $tmpdir/2nd-store
nix-store --add-fixed --recursive sha256 $tmpdir/directory --store $tmpdir/2nd-store
echo this will fail...
nix-instantiate --eval $result --store $tmpdir/2nd-store

The final nix-instantiate will trigger the throw from text.nix -- apparently filterSource confuses the store paths:

error: root path
/nix/store/dv15ix385vx19wxac0v5h5n7x8i5iwgp-directory
not prefix of path
/tmp/tmp.f3xsGxSb42/2nd-store/nix/store/dv15ix385vx19wxac0v5h5n7x8i5iwgp-directory/default.nix

Expected behavior

The final nix-instantiate invocation should succeed.

nix-env --version output

nix-env (Nix) 2.18.5

Additional context

Nixpkgs contains many instances of src = lib.fileset.toSouce { root = ./.; fileset = ..something..; } which are liable to trigger this bug if evaluated from within nixos-install; in that case src ends up as empty directory because the filter function from the fileset library constantly returns false. One such instance is documented (with steps to reproduce with nixos-install) in NixOS/nixpkgs#334098 .

Priorities

Add 👍 to issues you find important.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

⚖ To discuss

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions