From e21c23dd0b27b25a43562aba36e5478ee1947102 Mon Sep 17 00:00:00 2001 From: BirdeeHub Date: Thu, 10 Apr 2025 00:20:02 -0700 Subject: [PATCH] makeBinaryWrapper: --add-flags arguments now properly escaped avoids expanding variables, or globbing, handles backslash and quoting correctly --- .../makeBinaryWrapper/make-binary-wrapper.sh | 100 +++++++++++++++--- .../make-binary-wrapper/add-flags/add-flags.c | 31 +++++- .../add-flags/add-flags.cmdline | 16 ++- .../add-flags/add-flags.env | 22 ++++ 4 files changed, 148 insertions(+), 21 deletions(-) diff --git a/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh b/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh index 3948342a36fc9..bf3e910ab4e23 100644 --- a/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh +++ b/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh @@ -205,21 +205,8 @@ makeCWrapper() { addFlags() { local n flag before after var - # Disable file globbing, since bash will otherwise try to find - # filenames matching the the value to be prefixed/suffixed if - # it contains characters considered wildcards, such as `?` and - # `*`. We want the value as is, except we also want to split - # it on on the separator; hence we can't quote it. - local reenableGlob=0 - if [[ ! -o noglob ]]; then - reenableGlob=1 - fi - set -o noglob - # shellcheck disable=SC2086 - before=($1) after=($2) - if (( reenableGlob )); then - set +o noglob - fi + escapedArgsFromString before "$1" + escapedArgsFromString after "$2" var="argv_tmp" printf '%s\n' "char **$var = calloc(${#before[@]} + argc + ${#after[@]} + 1, sizeof(*$var));" @@ -240,6 +227,89 @@ addFlags() { printf '%s\n' "argv = $var;" } +# escapedArgsFromString ARRAYNAME "$INPUT" +# escapedArgsFromString ARRAYNAME <<< "$INPUT" +escapedArgsFromString() { + local outvarname="$1" + local input="${2:-$(cat)}" + local char='' token='' escape=0 quote='' + + local out=() + + while IFS= read -r -n1 char || [[ -n "$char" ]]; do + # it gives empty char when you get a newline + [[ -z "$char" ]] && char=$'\n' + + if (( escape )); then + token+="$char" + escape=0 + continue + fi + + case "$char" in + # in an argument list, \ within ' are ignored, but \ within " are not + \\) + if [[ $quote == "'" ]]; then + token+="$char" + else + escape=1 + fi + ;; + + "'") + if [[ $quote == '' ]]; then + quote="'" + elif [[ $quote == "'" ]]; then + quote='' + else + token+="$char" + fi + ;; + + '"') + if [[ $quote == '' ]]; then + quote='"' + elif [[ $quote == '"' ]]; then + quote='' + else + token+="$char" + fi + ;; + + [[:space:]]) + if [[ -n $quote ]]; then + token+="$char" + elif [[ -n $token ]]; then + out+=("$token") + token='' + fi + ;; + + $'\n') + if [[ -n $quote ]]; then + token+="$char" + elif [[ -n $token ]]; then + out+=("$token") + token='' + fi + ;; + + *) + token+="$char" + ;; + esac + done <<< "$input" + + # Add final token if needed + [[ -n $token ]] && out+=("$token") + + # set variable name given to the new array + eval "$outvarname=()" + for (( i=0; i<${#out[@]}; i++ )); do + eval "$(printf "$outvarname+=(%q)" "${out[i]}")" + done +} + # chdir DIR changeDir() { local dir diff --git a/pkgs/test/make-binary-wrapper/add-flags/add-flags.c b/pkgs/test/make-binary-wrapper/add-flags/add-flags.c index d998a5f6f983c..1364c0a087b4e 100644 --- a/pkgs/test/make-binary-wrapper/add-flags/add-flags.c +++ b/pkgs/test/make-binary-wrapper/add-flags/add-flags.c @@ -3,7 +3,7 @@ #include int main(int argc, char **argv) { - char **argv_tmp = calloc(6 + argc + 2 + 1, sizeof(*argv_tmp)); + char **argv_tmp = calloc(27 + argc + 2 + 1, sizeof(*argv_tmp)); assert(argv_tmp != NULL); argv_tmp[0] = argv[0]; argv_tmp[1] = "-x"; @@ -12,12 +12,33 @@ int main(int argc, char **argv) { argv_tmp[4] = "-abc"; argv_tmp[5] = "-g"; argv_tmp[6] = "*.txt"; + argv_tmp[7] = "some word"; + argv_tmp[8] = "some word"; + argv_tmp[9] = "-g"; + argv_tmp[10] = "*.txt *.lua $HOME"; + argv_tmp[11] = "$HOME"; + argv_tmp[12] = "--cmd"; + argv_tmp[13] = "lua testvar = true"; + argv_tmp[14] = "--cmd"; + argv_tmp[15] = "lua print(true)"; + argv_tmp[16] = "--cmd"; + argv_tmp[17] = "lua print(\"hello\")"; + argv_tmp[18] = "--cmd"; + argv_tmp[19] = "lua print('hello')"; + argv_tmp[20] = "--cmd"; + argv_tmp[21] = "lua print('$HOME')"; + argv_tmp[22] = "-g"; + argv_tmp[23] = "*.txt\n *.lua $HOME"; + argv_tmp[24] = "$HOME"; + argv_tmp[25] = "$word"; + argv_tmp[26] = "$word"; + argv_tmp[27] = "\\$word"; for (int i = 1; i < argc; ++i) { - argv_tmp[6 + i] = argv[i]; + argv_tmp[27 + i] = argv[i]; } - argv_tmp[6 + argc + 0] = "-foo"; - argv_tmp[6 + argc + 1] = "-bar"; - argv_tmp[6 + argc + 2] = NULL; + argv_tmp[27 + argc + 0] = "-foo"; + argv_tmp[27 + argc + 1] = "-bar"; + argv_tmp[27 + argc + 2] = NULL; argv = argv_tmp; argv[0] = "/send/me/flags"; diff --git a/pkgs/test/make-binary-wrapper/add-flags/add-flags.cmdline b/pkgs/test/make-binary-wrapper/add-flags/add-flags.cmdline index 1ca964ab4e7a7..7eff6d0d88a19 100644 --- a/pkgs/test/make-binary-wrapper/add-flags/add-flags.cmdline +++ b/pkgs/test/make-binary-wrapper/add-flags/add-flags.cmdline @@ -1,4 +1,18 @@ --append-flags "-foo -bar" \ --add-flags "-x -y -z" \ --add-flags -abc \ - --add-flags "-g *.txt" + --add-flags "-g *.txt" \ + --add-flags 'some\ word' \ + --add-flags some\\\ word \ + --add-flags '-g "*.txt *.lua $HOME" + \$HOME' \ + --add-flags "--cmd 'lua testvar = true'" \ + --add-flags "--cmd 'lua print(true)'" \ + --add-flags "--cmd 'lua print(\"hello\")'" \ + --add-flags '--cmd "lua print('\''hello'\'')"' \ + --add-flags '--cmd "lua print('\''$HOME'\'')"' \ + --add-flags '-g "*.txt + *.lua $HOME" + $HOME' \ + --add-flags '\$word "\$word"' \ + --add-flags ''\''\$word'\''' diff --git a/pkgs/test/make-binary-wrapper/add-flags/add-flags.env b/pkgs/test/make-binary-wrapper/add-flags/add-flags.env index f0641ef36f7c3..687ffca5b0252 100644 --- a/pkgs/test/make-binary-wrapper/add-flags/add-flags.env +++ b/pkgs/test/make-binary-wrapper/add-flags/add-flags.env @@ -6,5 +6,27 @@ SUBST_ARGV0 -abc -g *.txt +some word +some word +-g +*.txt *.lua $HOME +$HOME +--cmd +lua testvar = true +--cmd +lua print(true) +--cmd +lua print("hello") +--cmd +lua print('hello') +--cmd +lua print('$HOME') +-g +*.txt + *.lua $HOME +$HOME +$word +$word +\$word -foo -bar