[インデックス 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
関数の一部です。
toolName := args[0]
:go tool
コマンドに渡された最初の引数(これがツール名になります)をtoolName
変数に格納します。for _, c := range toolName
:toolName
文字列の各文字をループで処理します。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
が小文字の英字、数字、またはアンダースコアのいずれかであれば、有効な文字として扱われるようになります。
- 変更前:
default:
:switch
ステートメントのどのcase
にも一致しなかった場合(つまり、ツール名に許可されていない文字が含まれていた場合)に実行されます。fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\\n", toolName)
: 不正なツール名であることを示すエラーメッセージを標準エラー出力に表示します。setExitStatus(2)
: プログラムの終了ステータスを2に設定し、エラー終了を示します。
この変更により、go tool
コマンドは go_bootstrap
のようなアンダースコアを含むツール名を正しく認識し、実行できるようになりました。これは、Goツールチェーンの内部的な整合性と使いやすさを向上させるための重要な修正です。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- Go言語のツールコマンドに関するドキュメント: https://go.dev/cmd/go/ (特に
go tool
セクション)
参考にした情報源リンク
- 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
や関連ファイル