Skip to content

Hadrian's `lookupInPath` looks beyond `$PATH` variable on Windows

Summary

Hadrian's use of System.Directory.findExecutable leads to non-hermetic builds on Windows.

Steps to reproduce

Hadrian's lookupInPath oracle is currently implemented via System.Directory.findExecutable:

    void $ addOracleCache $ \(LookupInPath name) -> do
        let unpack = fromMaybe . error $ "Cannot find executable " ++ quote name
        path <- unifyPath . unpack <$> liftIO (findExecutable name)
        putLoud $ "| Executable found: " ++ name ++ " => " ++ path
        return path

Note the haddock for findDirectory. It has special behavior on Windows, where it will query the "SearchPath". That path will include C:/Windows/System32/.

Why is that a problem? Well, in order to debug !4833 (closed), I needed to build GHC on my local Windows machine. I started from a clean slate my nuking my msys2 install. I followed all the rules from https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation/windows (and fixed a few bitrotting bugs). Then, after a successful boot and configure (with autotarballs-download), I started the GHC build via hadrian, which failed while configuring gmp: "m4: Command not found". Why?

It turns out that because I also have WSL installed, the lookup of bashPath in hadrian would find C:/Windows/System32/bash.exe and run configure in the environment of the WSL's bash! Chaos.

Proposal

Don't use findExecutable, or somehow tell it not to meddle outside $PATH.

Environment

  • GHC version used: 8.10.2
  • Operating System: Windows
Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information