Quoting various characters that the shell *may* interpret specially is a
very fragile thing to do.
I've used something more robust all over the place in various Nix
expression I've written just because I didn't trust escapeShellArg.
Here is a proof of concept showing that I was indeed right in
distrusting escapeShellArg:
with import <nixpkgs> {};
let
payload = runCommand "payload" {} ''
# \x00 is not allowed for Nix strings, so let's begin at 1
for i in $(seq 1 255); do
echo -en "\\x$(printf %02x $i)"
done > "$out"
'';
escapers = with lib; {
current = escapeShellArg;
better = arg: let
backslashEscapes = stringToCharacters "\"\\ ';$`()|<>\r\t*[]&!~#";
search = backslashEscapes ++ [ "\n" ];
replace = map (c: "\\${c}") backslashEscapes ++ [ "'\n'" ];
in replaceStrings search replace (toString arg);
best = arg: "'${replaceStrings ["'"] ["'\\''"] (toString arg)}'";
};
testWith = escaper: let
escaped = escaper (builtins.readFile payload);
in runCommand "test" {} ''
if ! r="$(bash -c ${escapers.best "echo -nE ${escaped}"} 2> /dev/null)"
then
echo bash eval error > "$out"
exit 0
fi
if echo -n "$r" | cmp -s "${payload}"; then
echo success > "$out"
else
echo failed > "$out"
fi
'';
in runCommand "results" {} ''
echo "Test results:"
${lib.concatStrings (lib.mapAttrsToList (name: impl: ''
echo " ${name}: $(< "${testWith impl}")"
'') escapers)}
exit 1
''
The resulting output is the following:
Test results:
best: success
better: success
current: bash eval error
I did the "better" implementation just to illustrate that the method of
quoting only "harmful" characters results in madness in terms of
implementation and performance.
Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Cc: @edolstra, @zimbatm
Nixpkgs is a collection of packages for the Nix package manager. It is periodically built and tested by the hydra build daemon as so-called channels. To get channel information via git, add nixpkgs-channels as a remote:
% git remote add channels git://github.com/NixOS/nixpkgs-channels.git
For stability and maximum binary package support, it is recommended to maintain
custom changes on top of one of the channels, e.g. nixos-16.03 for the latest
release and nixos-unstable for the latest successful build of master:
% git remote update channels
% git rebase channels/nixos-16.03
For pull-requests, please rebase onto nixpkgs master.
NixOS linux distribution source code is located inside
nixos/ folder.
- NixOS installation instructions
- Documentation (Nix Expression Language chapter)
- Manual (How to write packages for Nix)
- Manual (NixOS)
- Nix Wiki
- Continuous package builds for unstable/master
- Continuous package builds for 16.03 release
- Tests for unstable/master
- Tests for 16.03 release
Communication:
Description
Languages
Nix
96.3%
Shell
1.8%
Python
0.7%
Perl
0.4%
C
0.3%
Other
0.1%
