wrapBintoolsWith: support LINK.EXE-style args in purity checks

LLD supports Windows-style linker arguments, but these previously
triggered purity check false positives, because it saw that they
started with a '/' and assumed they were paths.

This tweaks the path detection to allow through certain values that
could be paths, but are much more likely to be LINK.EXE-style flags.
The risk of false negatives here is low — the only things we'd now
fail to catch would be attempts to link with libraries in the root
directory, which doesn't happen in practice.

We also teach the wrapper how to apply its purity checks to library
paths specified with the /LIBPATH: option.

Tested that paths we expect to be rejected (like /lib/libfoo.so) still
are.
This commit is contained in:
Alyssa Ross 2023-04-28 23:26:42 +00:00
parent 0949f3cd78
commit 194ddeefd5
No known key found for this signature in database
GPG key ID: F9DBED4859B271C0
2 changed files with 12 additions and 5 deletions

View file

@ -55,10 +55,12 @@ if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
# produces '-syslibroot //' linker flag. It's a no-op, # produces '-syslibroot //' linker flag. It's a no-op,
# which does not introduce impurities. # which does not introduce impurities.
n+=1; skip "$p2" n+=1; skip "$p2"
elif [ "${p:0:1}" = / ] && badPath "$p"; then elif [ "${p:0:10}" = /LIBPATH:/ ] && badPath "${p:9}"; then
# We cannot skip this; barf. reject "${p:9}"
echo "impure path \`$p' used in link" >&2 # We need to not match LINK.EXE-style flags like
exit 1 # /NOLOGO or /LIBPATH:/nix/store/foo
elif [[ $p =~ ^/[^:]*/ ]] && badPath "$p"; then
reject "$p"
elif [ "${p:0:9}" = --sysroot ]; then elif [ "${p:0:9}" = --sysroot ]; then
# Our ld is not built with sysroot support (Can we fix that?) # Our ld is not built with sysroot support (Can we fix that?)
: :

View file

@ -84,12 +84,17 @@ mangleVarSingle() {
done done
} }
skip () { skip() {
if (( "${NIX_DEBUG:-0}" >= 1 )); then if (( "${NIX_DEBUG:-0}" >= 1 )); then
echo "skipping impure path $1" >&2 echo "skipping impure path $1" >&2
fi fi
} }
reject() {
echo "impure path \`$1' used in link" >&2
exit 1
}
# Checks whether a path is impure. E.g., `/lib/foo.so' is impure, but # Checks whether a path is impure. E.g., `/lib/foo.so' is impure, but
# `/nix/store/.../lib/foo.so' isn't. # `/nix/store/.../lib/foo.so' isn't.