Check that toolchain is passed exactly one argument

The toolchain function was not checking that the number of
passed argument was correct (and thus accessing a vector
at an invalid index which is undefined behaviour).

Insert call to EnsureSingleStringArg to reuse the generic
check shared by other generic function.

Bug: 45
Change-Id: I9d06fba50d94d5d542dfaff45d378ffe78958803
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/9021
Commit-Queue: Nico Weber <thakis@chromium.org>
Reviewed-by: Nico Weber <thakis@chromium.org>
diff --git a/src/gn/function_toolchain.cc b/src/gn/function_toolchain.cc
index 92721dc..0ff5d34 100644
--- a/src/gn/function_toolchain.cc
+++ b/src/gn/function_toolchain.cc
@@ -196,6 +196,9 @@
       !EnsureNotProcessingBuildConfig(function, scope, err))
     return Value();
 
+  if (!EnsureSingleStringArg(function, args, err))
+    return Value();
+
   // Note that we don't want to use MakeLabelForScope since that will include
   // the toolchain name in the label, and toolchain labels don't themselves
   // have toolchain names.
diff --git a/src/gn/function_toolchain_unittest.cc b/src/gn/function_toolchain_unittest.cc
index 2229495..ba4bfb6 100644
--- a/src/gn/function_toolchain_unittest.cc
+++ b/src/gn/function_toolchain_unittest.cc
@@ -11,6 +11,30 @@
 
 using FunctionToolchain = TestWithScheduler;
 
+TEST_F(FunctionToolchain, NoArguments) {
+  TestWithScope setup;
+
+  // Check that creating a toolchain with no name reports an error.
+  {
+    TestParseInput input(R"(toolchain() {})");
+    ASSERT_FALSE(input.has_error());
+
+    Err err;
+    input.parsed()->Execute(setup.scope(), &err);
+    ASSERT_TRUE(err.has_error()) << err.message();
+  }
+
+  // Check that creating a toolchain with too many arguments is an error.
+  {
+    TestParseInput input(R"(toolchain("too", "many", "arguments") {})");
+    ASSERT_FALSE(input.has_error());
+
+    Err err;
+    input.parsed()->Execute(setup.scope(), &err);
+    ASSERT_TRUE(err.has_error()) << err.message();
+  }
+}
+
 TEST_F(FunctionToolchain, RuntimeOutputs) {
   TestWithScope setup;