bazelbuild/bazel

sh_binary launcher does not quote arguments correctly on Windows

Open

#17,487 创建于 2023年2月14日

在 GitHub 查看
 (6 评论) (2 反应) (0 负责人)Java (4,465 fork)batch import
P3area-Windowshelp wantedteam-Rules-Servertype: bug

仓库指标

Star
 (25,384 star)
PR 合并指标
 (平均合并 22天 20小时) (30 天内合并 77 个 PR)

描述

Description of the bug:

When using the sh_binary rule to invoke a bash program on Windows, the BashBinaryLauncher C++ class used to invoke bash composes the command-line arguments incorrectly, quoting only those arguments that include at least one space character and escaping only double quotation and backslash characters. The launcher fails to quote arguments that include other characters that bash winds up misinterpreting.

In short, even when the sh_binary author quotes the command-line arguments as necessary to satisfy bash, the BashBinaryLauncher program consumes those arguments but then fails to emit them again in a manner that will satisfy bash.

What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

Find attached here an archive of a Bazel repository named bazel-sh-binary-test. After extracting that archive, run the following command:

bazel test //test:print_args_test

This test compares the would-be printed output with expected "golden" output. This test succeeds on macOS and Linux.

When run on Windows, though, we never even make it as far as invoking the bash program in file test/print-args. Instead, bash fails while parsing the command-line arguments passed via the -c flag by the BashBinaryLauncher program.

In the genrule target named "capture_printed_args," we invoke the print-args program as follows:

print_args a 'b c' 'f(x).y'

Note that the final argument is f(x).y surrounded by single quotation marks. Quoting the argument like that is necessary because the parentheses are shell metacharacters. We don't intend for bash to interpret those parentheses; they're meant for the print-args program to receive and consume.

Bazel's genrule implementation invokes the program created by the sh_binary rule as follows:

.../bin/test/print_args.exe a 'b c' 'f(x).y' > "bazel-out/.../bin/test/printed-args.txt"

Note that the second b c and third f(x).y arguments are both surrounded by single quotation marks. Next, the print_args.exe program invokes bash as follows:

...\usr\bin\bash.exe -c '...\bin\test\print_args a "b c" f(x).y'

Note that while the second b c argument is surrounded with double quotation marks, the third f(x).y argument is not quoted at all. BashBinaryLauncher decided that that third argument didn't warrant quoting, but then bash fails as follows:

/usr/bin/bash: -c: line 1: syntax error near unexpected token `('

Which operating system are you running Bazel on?

Windows

What is the output of bazel info release?

release 6.0.0

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

No response

What's the output of git remote get-url origin; git rev-parse master; git rev-parse HEAD ?

No response

Have you found anything relevant by searching the web?

Somewhat related issues:

  • #4778
  • #7122
  • #9106
  • #9108

Somewhat related PRs:

  • #9123

Any other information, logs, or outputs that you want to share?

There have been a few discussions in the "Bazel" Slack workspace on this subject, most recently focused on interpreting the failures with the test case supplied here. As part of that discussion, @fmeum submitted #17484 to probe the argument inspection and escaping done in the BashEscapeArg function.

The bash source code offers the sh_contains_shell_metas function that shows which characters bash itself considers to warrant special treatment. Among other things, bash uses that function to determine when to quote words when printing commands. Looking there, space characters are just one of twenty-five possible characters that may warrant quoting.

Without us being more conservative in which arguments we quote before passing on to the sh_binary-wrapped program, we can't pass many otherwise valid arguments through, leaving us unable to support invocations on Windows that work fine in other operating systems, even though we have bash at our disposal.

贡献者指南