Restrict bazelrc-set flag aliases to the "build" command.
This prevents being able to build with an alias that "$ bazel
canonicalize-flags" doesn't understand. This is a safety check for build and CI
pipelines that process invocation flags through canonicalize-flags.
Example scenario this fixes:
$ cat .bazelrc
test --flag_alias=myalias=//foo
build:myconfig --flag_alias=configalias=//foo
build:myconfig --configalias=5
$ bazel test //:mytest --myalias=blah
<succeeds>
$ bazel canonicalize-flags --for_command=test -- --myalias=blah
ERROR: Unrecognized option: --myalias=blah
$ bazel build //:mybuild --config=myconfig
<succeeds>
$ bazel canonicalize-flags -- --configalias=4
ERROR: Unrecognized option: --configalias=4
We could potentially expand CanonicalizeCommand.java to inherit from
TestCommand.class instead of BuildCommand.class if there was a use case for
loosening this restriction.
PiperOrigin-RevId: 374867565
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
index ca0ba67..50e2495 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeOptionHandler.java
@@ -31,6 +31,7 @@
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.InvocationPolicyEnforcer;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionPriority.PriorityCategory;
@@ -428,7 +429,8 @@
EventHandler eventHandler,
List<String> rcFiles,
List<ClientOptions.OptionOverride> rawOverrides,
- Set<String> validCommands) {
+ Set<String> validCommands)
+ throws OptionsParsingException {
ListMultimap<String, RcChunkOfArgs> commandToRcArgs = ArrayListMultimap.create();
String lastRcFile = null;
@@ -440,6 +442,21 @@
continue;
}
String rcFile = rcFiles.get(override.blazeRc);
+ // The canonicalize-flags command only inherits bazelrc "build" commands. Not "test", not
+ // "build:foo". Restrict --flag_alias accordingly to prevent building with flags that
+ // canonicalize-flags can't recognize.
+ if ((override.option.startsWith("--" + Converters.BLAZE_ALIASING_FLAG + "=")
+ || override.option.equals("--" + Converters.BLAZE_ALIASING_FLAG))
+ // In production, "build" is always a valid command, but not necessarily in tests.
+ // Particularly C0Command, which some tests use for low-level options parsing logic. We
+ // don't want to interfere with those.
+ && validCommands.contains("build")
+ && !override.command.equals("build")) {
+ throw new OptionsParsingException(
+ String.format(
+ "%s: \"%s %s\" disallowed. --%s only supports the \"build\" command.",
+ rcFile, override.command, override.option, Converters.BLAZE_ALIASING_FLAG));
+ }
String command = override.command;
int index = command.indexOf(':');
if (index > 0) {
diff --git a/src/test/shell/integration/starlark_configurations_test.sh b/src/test/shell/integration/starlark_configurations_test.sh
index 0bacffa..ddf298f 100755
--- a/src/test/shell/integration/starlark_configurations_test.sh
+++ b/src/test/shell/integration/starlark_configurations_test.sh
@@ -56,7 +56,10 @@
export MSYS2_ARG_CONV_EXCL="*"
fi
-add_to_bazelrc "build --package_path=%workspace%"
+function set_up() {
+ write_default_bazelrc
+ add_to_bazelrc "build --package_path=%workspace%"
+}
#### HELPER FXNS #######################################################
@@ -635,4 +638,67 @@
expect_log "--//$pkg:type=coffee"
}
+function test_rc_flag_alias_unsupported_under_test_command() {
+ local -r pkg=$FUNCNAME
+ mkdir -p $pkg
+
+ add_to_bazelrc "test --flag_alias=drink=//$pkg:type"
+ write_build_setting_bzl
+
+ bazel canonicalize-flags -- --drink=coffee \
+ >& "$TEST_log" && fail "Expected failure"
+ expect_log "--flag_alias=drink=//$pkg:type\" disallowed. --flag_alias only "\
+"supports the \"build\" command."
+
+ bazel build //$pkg:my_drink >& "$TEST_log" && fail "Expected failure"
+ expect_log "--flag_alias=drink=//$pkg:type\" disallowed. --flag_alias only "\
+"supports the \"build\" command."
+
+ # Post-test cleanup_workspace() calls "bazel clean", which would also fail
+ # unless we reset the bazelrc.
+ write_default_bazelrc
+}
+
+function test_rc_flag_alias_unsupported_under_conditional_build_command() {
+ local -r pkg=$FUNCNAME
+ mkdir -p $pkg
+
+ add_to_bazelrc "build:foo --flag_alias=drink=//$pkg:type"
+ write_build_setting_bzl
+
+ bazel canonicalize-flags -- --drink=coffee \
+>& "$TEST_log" && fail "Expected failure"
+ expect_log "--flag_alias=drink=//$pkg:type\" disallowed. --flag_alias only "\
+"supports the \"build\" command."
+
+ bazel build //$pkg:my_drink >& "$TEST_log" && fail "Expected failure"
+ expect_log "--flag_alias=drink=//$pkg:type\" disallowed. --flag_alias only "\
+"supports the \"build\" command."
+
+ # Post-test cleanup_workspace() calls "bazel clean", which would also fail
+ # unless we reset the bazelrc.
+ write_default_bazelrc
+}
+
+function test_rc_flag_alias_unsupported_with_space_assignment_syntax() {
+ local -r pkg=$FUNCNAME
+ mkdir -p $pkg
+
+ add_to_bazelrc "test --flag_alias drink=//$pkg:type"
+ write_build_setting_bzl
+
+ bazel canonicalize-flags -- --drink=coffee \
+ >& "$TEST_log" && fail "Expected failure"
+ expect_log "--flag_alias\" disallowed. --flag_alias only "\
+"supports the \"build\" command."
+
+ bazel build //$pkg:my_drink >& "$TEST_log" && fail "Expected failure"
+ expect_log "--flag_alias\" disallowed. --flag_alias only "\
+"supports the \"build\" command."
+
+ # Post-test cleanup_workspace() calls "bazel clean", which would also fail
+ # unless we reset the bazelrc.
+ write_default_bazelrc
+}
+
run_suite "${PRODUCT_NAME} starlark configurations tests"