Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12746] ファイルの概要

このコミットは、Go言語のコマンドラインツールである cmd/go の内部ロジックを修正するものです。具体的には、src/cmd/go/tool.go ファイル内のツール名の検証ロジックが変更されています。

コミット

このコミットは、Goツールチェーンの一部である cmd/go コマンドが、ツール名にアンダースコア (_) を含むことを許可するように変更します。これにより、go_bootstrap のようなアンダースコアを含むツールを直接呼び出すことが可能になります。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/304404895d2204f0557da4753684689198e20ccd

元コミット内容

commit 304404895d2204f0557da4753684689198e20ccd
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Mon Mar 26 10:01:17 2012 +0800

    cmd/go: allow underscores in tool name
            Otherwise we can't invoke go_bootstrap directly.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5900061

変更の背景

Go言語のツールチェーンには、go_bootstrap と呼ばれる内部ツールが存在します。これは、Goコンパイラやその他のツールをビルドする際に使用されるブートストラッププロセスの一部です。しかし、このコミットが適用される前は、cmd/go コマンドがツール名を検証する際に、ツール名に小文字の英字と数字のみを許可していました。

この厳格な検証ルールのため、go_bootstrap のように名前にアンダースコアを含むツールは、go tool コマンドを通じて直接呼び出すことができませんでした。これは、開発やデバッグの際に不便であり、ブートストラッププロセスを円滑に進める上で制約となっていました。このコミットは、この制約を取り除き、アンダースコアを含むツール名も正しく認識・実行できるようにするために導入されました。

前提知識の解説

Goツールチェーン (cmd/go)

cmd/go は、Go言語のソースコードのコンパイル、パッケージの管理、テストの実行、ドキュメントの生成など、Go開発における主要なタスクを処理するためのコマンドラインツールです。go build, go run, go test, go get など、開発者が日常的に使用する多くのサブコマンドを提供します。

go tool コマンド

go tool は、Goツールチェーンに含まれる低レベルのツール(例: アセンブラ asm、リンカ link、コンパイラ compile など)を実行するためのサブコマンドです。通常、これらのツールは go build などの高レベルなコマンドによって内部的に呼び出されますが、開発者が特定のツールを直接実行したい場合に go tool <toolname> の形式で使用します。

go_bootstrap

go_bootstrap は、Go言語のコンパイラや標準ライブラリをビルドする際に使用される特別なツールです。Go言語は自己ホスト型(self-hosted)であり、Goコンパイラ自体がGo言語で書かれています。そのため、新しいバージョンのGoをビルドする際には、既存のGoコンパイラ(または以前のバージョンのGoコンパイラ)を使用して、新しいコンパイラを「ブートストラップ」する必要があります。go_bootstrap はこのブートストラッププロセスの一部として機能し、Goツールチェーンのビルドの初期段階で重要な役割を果たします。その名前が示す通り、ブートストラップの目的のためにアンダースコアが含まれています。

ツール名の検証

cmd/go は、セキュリティやコマンドの整合性を保つために、go tool コマンドで指定されるツール名に対して一定の検証を行います。この検証は、不正な文字の使用を防ぎ、予期せぬコマンド実行を防ぐことを目的としています。このコミット以前は、この検証が厳しすぎたため、正当な内部ツールである go_bootstrap が実行できないという問題がありました。

技術的詳細

この変更は、src/cmd/go/tool.go ファイル内の runTool 関数にあります。この関数は、go tool コマンドが呼び出された際に、指定されたツール名の妥当性をチェックするロジックを含んでいます。

変更前のコードでは、ツール名に使用できる文字を小文字の英字 ('a' から 'z') と数字 ('0' から '9') に限定していました。これは for ループ内で各文字をイテレートし、switch ステートメントで文字の範囲をチェックすることで実装されていました。

変更後のコードでは、この switch ステートメントに新しいケースが追加され、アンダースコア ('_') も有効な文字として認識されるようになりました。

具体的には、以下の行が変更されました。

変更前:

case 'a' <= c && c <= 'z', '0' <= c && c <= '9':

変更後:

case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':

この変更により、toolName の各文字が小文字の英字、数字、またはアンダースコアのいずれかであれば、検証を通過するようになります。それ以外の文字が見つかった場合は、エラーメッセージ ("go tool: bad tool name %q") が標準エラー出力に表示され、プログラムは終了ステータス2で終了します。

この修正は、ツール名の検証ロジックをより柔軟にし、go_bootstrap のような正当な内部ツールが go tool コマンドを通じて正しく機能するようにするために必要でした。

コアとなるコードの変更箇所

--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -59,10 +59,10 @@ func runTool(cmd *Command, args []string) {
 		return
 	}
 	toolName := args[0]
-	// The tool name must be lower-case letters and numbers.
+	// The tool name must be lower-case letters, numbers or underscores.
 	for _, c := range toolName {
 		switch {
-		case 'a' <= c && c <= 'z', '0' <= c && c <= '9':
+		case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
 		default:
 			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName)
 			setExitStatus(2)

コアとなるコードの解説

変更されたコードは、src/cmd/go/tool.go ファイル内の runTool 関数の一部です。

  1. toolName := args[0]: go tool コマンドに渡された最初の引数(これがツール名になります)を toolName 変数に格納します。
  2. for _, c := range toolName: toolName 文字列の各文字をループで処理します。
  3. switch ステートメント: 各文字 c が有効な文字であるかをチェックします。
    • 変更前: case 'a' <= c && c <= 'z', '0' <= c && c <= '9': この行は、文字 c が小文字の英字('a'から'z')または数字('0'から'9')の範囲内にある場合に true となります。つまり、これらの文字のみが許可されていました。
    • 変更後: case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_': この行は、既存の条件に加えて c == '_' という条件が追加されています。これにより、文字 c が小文字の英字、数字、またはアンダースコアのいずれかであれば、有効な文字として扱われるようになります。
  4. default:: switch ステートメントのどの case にも一致しなかった場合(つまり、ツール名に許可されていない文字が含まれていた場合)に実行されます。
    • fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName): 不正なツール名であることを示すエラーメッセージを標準エラー出力に表示します。
    • setExitStatus(2): プログラムの終了ステータスを2に設定し、エラー終了を示します。

この変更により、go tool コマンドは go_bootstrap のようなアンダースコアを含むツール名を正しく認識し、実行できるようになりました。これは、Goツールチェーンの内部的な整合性と使いやすさを向上させるための重要な修正です。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/ (コミットメッセージに記載されている https://golang.org/cl/5900061 は、このGerritシステムへのリンクです。)
  • go_bootstrap に関する情報 (Go言語のブートストラッププロセスについて):
    • Goのブートストラップに関する一般的な情報源 (例: Goのビルドプロセスに関するブログ記事やドキュメント)
    • Goのソースコード内の src/cmd/go/bootstrap.go や関連ファイル